Skip to content

Commit

Permalink
Sort Picker Changes (#1494)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sjmarf authored Dec 17, 2024
1 parent 20837e4 commit 45ed9d0
Show file tree
Hide file tree
Showing 18 changed files with 557 additions and 123 deletions.
20 changes: 20 additions & 0 deletions Mlem.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@
0369B3562BFA6824001EFEDF /* InboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0369B3552BFA6824001EFEDF /* InboxView.swift */; };
0369B35D2BFB86E3001EFEDF /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0369B35A2BFB86E3001EFEDF /* Account.swift */; };
036CC3AF2B8145C30098B6A1 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036CC3AE2B8145C30098B6A1 /* AppState.swift */; };
036ED6792D0AF3740018E5EA /* PinnedSortTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036ED6782D0AF3740018E5EA /* PinnedSortTracker.swift */; };
036ED67B2D0B004D0018E5EA /* AdvancedSortView+SortButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036ED67A2D0B004D0018E5EA /* AdvancedSortView+SortButton.swift */; };
036ED67D2D0B006C0018E5EA /* TopSortPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036ED67C2D0B006C0018E5EA /* TopSortPicker.swift */; };
036ED67F2D0B9A520018E5EA /* CommunitySearchSortPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036ED67E2D0B9A520018E5EA /* CommunitySearchSortPicker.swift */; };
036ED6832D0C483B0018E5EA /* Profile2Providing+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036ED6822D0C483B0018E5EA /* Profile2Providing+Extensions.swift */; };
037331A42C9CB12D00C826E1 /* EnvironmentValues+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037331A32C9CB12D00C826E1 /* EnvironmentValues+Extensions.swift */; };
037386472BDAFE81007492B5 /* LemmyMarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = 037386462BDAFE81007492B5 /* LemmyMarkdownUI */; };
Expand Down Expand Up @@ -157,6 +161,7 @@
0389DDDB2C3AB6340005B808 /* ActionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0389DDDA2C3AB6340005B808 /* ActionBuilder.swift */; };
0391E0F92CFF17AE0040CCA8 /* ProfileSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0391E0F82CFF17AE0040CCA8 /* ProfileSettingsView.swift */; };
0391E0FB2D0066240040CCA8 /* ImageUploadMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0391E0FA2D0066240040CCA8 /* ImageUploadMenu.swift */; };
0391E0FE2D05B2DF0040CCA8 /* AdvancedSortView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0391E0FD2D05B2DF0040CCA8 /* AdvancedSortView.swift */; };
0397D4602C66113F002C6CDC /* CommentBodyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0397D45F2C66113F002C6CDC /* CommentBodyView.swift */; };
0397D4622C676B46002C6CDC /* ApiSortType+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0397D4612C676B46002C6CDC /* ApiSortType+Extensions.swift */; };
0397D4642C676CA8002C6CDC /* FeedSortPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0397D4632C676CA8002C6CDC /* FeedSortPicker.swift */; };
Expand Down Expand Up @@ -553,6 +558,10 @@
0369B3552BFA6824001EFEDF /* InboxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxView.swift; sourceTree = "<group>"; };
0369B35A2BFB86E3001EFEDF /* Account.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = "<group>"; };
036CC3AE2B8145C30098B6A1 /* AppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = "<group>"; };
036ED6782D0AF3740018E5EA /* PinnedSortTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedSortTracker.swift; sourceTree = "<group>"; };
036ED67A2D0B004D0018E5EA /* AdvancedSortView+SortButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AdvancedSortView+SortButton.swift"; sourceTree = "<group>"; };
036ED67C2D0B006C0018E5EA /* TopSortPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopSortPicker.swift; sourceTree = "<group>"; };
036ED67E2D0B9A520018E5EA /* CommunitySearchSortPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunitySearchSortPicker.swift; sourceTree = "<group>"; };
036ED6822D0C483B0018E5EA /* Profile2Providing+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Profile2Providing+Extensions.swift"; sourceTree = "<group>"; };
037331A32C9CB12D00C826E1 /* EnvironmentValues+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+Extensions.swift"; sourceTree = "<group>"; };
037658DE2BE7D9EF00F4DD4D /* Community1Providing+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Community1Providing+Extensions.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -583,6 +592,7 @@
0389DDDA2C3AB6340005B808 /* ActionBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionBuilder.swift; sourceTree = "<group>"; };
0391E0F82CFF17AE0040CCA8 /* ProfileSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileSettingsView.swift; sourceTree = "<group>"; };
0391E0FA2D0066240040CCA8 /* ImageUploadMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageUploadMenu.swift; sourceTree = "<group>"; };
0391E0FD2D05B2DF0040CCA8 /* AdvancedSortView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSortView.swift; sourceTree = "<group>"; };
0397D45F2C66113F002C6CDC /* CommentBodyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentBodyView.swift; sourceTree = "<group>"; };
0397D4612C676B46002C6CDC /* ApiSortType+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ApiSortType+Extensions.swift"; sourceTree = "<group>"; };
0397D4632C676CA8002C6CDC /* FeedSortPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedSortPicker.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -992,6 +1002,10 @@
033FCAF32C59843E007B7CD1 /* CommunityView.swift */,
03049A212C650B2C00FF6889 /* CommunityDetailsView.swift */,
0397D4632C676CA8002C6CDC /* FeedSortPicker.swift */,
036ED67C2D0B006C0018E5EA /* TopSortPicker.swift */,
036ED67E2D0B9A520018E5EA /* CommunitySearchSortPicker.swift */,
0391E0FD2D05B2DF0040CCA8 /* AdvancedSortView.swift */,
036ED67A2D0B004D0018E5EA /* AdvancedSortView+SortButton.swift */,
);
path = Community;
sourceTree = "<group>";
Expand Down Expand Up @@ -1899,6 +1913,7 @@
CDE1F18E2C63D75A008AF042 /* Settings.swift */,
CDE1F19B2C63E2EB008AF042 /* SettingPropertyWrapper.swift */,
0315B1C92C767847006D4F82 /* InteractionBarTracker.swift */,
036ED6782D0AF3740018E5EA /* PinnedSortTracker.swift */,
CDD4A09B2C8A122F0001AD1A /* CodableSettings.swift */,
);
path = "User Settings";
Expand Down Expand Up @@ -2194,6 +2209,7 @@
CD7928232C73CBA400FA712D /* TileScoreView.swift in Sources */,
03AF91E12C1B25DE00E56644 /* UIDevice+Extensions.swift in Sources */,
0389DDC52C38917A0005B808 /* InboxItemProviding+Extensions.swift in Sources */,
036ED67B2D0B004D0018E5EA /* AdvancedSortView+SortButton.swift in Sources */,
CD13CC5B2C588B34001AF428 /* WebView.swift in Sources */,
CDB41E8C2C84CED500BD2DE9 /* FixedImageLoader.swift in Sources */,
039EFEC32BEEBEE0003AC372 /* LoginInstancePickerView.swift in Sources */,
Expand Down Expand Up @@ -2225,6 +2241,7 @@
03134A522BEAD69F002662CC /* SettingsPage.swift in Sources */,
03049A1C2C65039400FF6889 /* ActiveUserCountView.swift in Sources */,
0389DDDB2C3AB6340005B808 /* ActionBuilder.swift in Sources */,
036ED67F2D0B9A520018E5EA /* CommunitySearchSortPicker.swift in Sources */,
038028FA2CB097CB0091A8A2 /* SearchView+LocationPicker.swift in Sources */,
CDD8B94C2C8234BC00510EBB /* Form.swift in Sources */,
0320B6652C91DBD500D38548 /* NavigationPage+View.swift in Sources */,
Expand Down Expand Up @@ -2392,6 +2409,7 @@
CD4D58DA2B86E11D00B82964 /* Mockable.swift in Sources */,
034B94892C09360A00039AF4 /* Int+Extensions.swift in Sources */,
039D75642C4EEE69004F24C2 /* DeletableProviding+Extensions.swift in Sources */,
0391E0FE2D05B2DF0040CCA8 /* AdvancedSortView.swift in Sources */,
0315B1C82C7635D4006D4F82 /* ApiCommentSortType+Extensions.swift in Sources */,
035394972CA1AFAF00795AA5 /* InstanceStubProviding+Uptime.swift in Sources */,
CDB2EC882BFAE14800DBC0EF /* FullyQualifiedNameView.swift in Sources */,
Expand Down Expand Up @@ -2445,6 +2463,7 @@
03A82FA32C0D1F2400D01A5C /* View+ExternalApiWarning.swift in Sources */,
033F84C32C2B12AA002E3EDF /* InstanceSummary.swift in Sources */,
0369B3532BFA514B001EFEDF /* ToastLocation.swift in Sources */,
036ED6792D0AF3740018E5EA /* PinnedSortTracker.swift in Sources */,
0353948D2CA080EB00795AA5 /* FeedWelcomeView.swift in Sources */,
03049A202C650A8100FF6889 /* FormReadout.swift in Sources */,
0397D49A2C6EA6EE002C6CDC /* InteractionBarEditorView.swift in Sources */,
Expand All @@ -2468,6 +2487,7 @@
032C320C2C3482CA00595286 /* Person1Providing+Extensions.swift in Sources */,
038028D32CAB3D2D0091A8A2 /* ShareActivity.swift in Sources */,
CD09BA7F2CB4698E00C93926 /* OledPalette.swift in Sources */,
036ED67D2D0B006C0018E5EA /* TopSortPicker.swift in Sources */,
030FF67F2BC8544700F6BFAC /* CustomTabBarController.swift in Sources */,
CD4D58F82B87B0D100B82964 /* InternetSpeed.swift in Sources */,
0353949C2CA4B3E800795AA5 /* CrossPostListView.swift in Sources */,
Expand Down
29 changes: 29 additions & 0 deletions Mlem/App/Configuration/User Settings/PinnedSortTracker.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// PinnedSortTracker.swift
// Mlem
//
// Created by Sjmarf on 2024-12-12.
//

import Dependencies
import Foundation
import MlemMiddleware
import Observation

@Observable
class PinnedSortTracker {
@ObservationIgnored @Dependency(\.persistenceRepository)
private var persistenceRepository

var pinnedSortTypes: Set<ApiSortType> {
didSet { Task.detached {
try await self.persistenceRepository.savePinnedSortTypes(self.pinnedSortTypes)
} }
}

init() {
self.pinnedSortTypes = PersistenceRepository.liveValue.loadPinnedSortTypes()
}

public static let main: PinnedSortTracker = .init()
}
11 changes: 11 additions & 0 deletions Mlem/App/Globals/Definitions/PersistenceRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ private enum Path {
static var easterFlags = root.appendingPathComponent("Easter eggs flags", conformingTo: .json)
static var instanceMetadata = root.appendingPathComponent("Instance Metadata", conformingTo: .json)
static var layoutWidgets = root.appendingPathComponent("Layout Widgets", conformingTo: .json)
static var pinnedSortTypes = root.appendingPathComponent("Sort Settings", conformingTo: .json)
static var systemSettings = root.appendingPathComponent("System Settings", conformingTo: .directory)
static var userSettings = root.appendingPathComponent("User Settings", conformingTo: .directory)
}
Expand Down Expand Up @@ -156,6 +157,16 @@ class PersistenceRepository {
try await save(value, to: Path.layoutWidgets)
}

func loadPinnedSortTypes() -> Set<ApiSortType> {
load(Set<ApiSortType>.self, from: Path.pinnedSortTypes) ?? [
.hot, .new, .topSixHour, .topDay, .topWeek, .topMonth, .topYear, .topAll
]
}

func savePinnedSortTypes(_ value: Set<ApiSortType>) async throws {
try await save(value, to: Path.pinnedSortTypes)
}

/// Saves the given user settings
func saveUserSettings(_ settings: CodableSettings, name: String) async throws {
try await save(settings, to: Path.userSettings.appendingPathComponent(name, conformingTo: .json))
Expand Down
2 changes: 1 addition & 1 deletion Mlem/App/Utility/Extensions/AVPlayer+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ import AVFoundation

extension AVPlayer {
func isAudioAvailable() async throws -> Bool? {
return try await self.currentItem?.asset.loadTracks(withMediaType: .audio).count != 0
try await currentItem?.asset.loadTracks(withMediaType: .audio).count != 0
}
}
100 changes: 75 additions & 25 deletions Mlem/App/Utility/Extensions/ApiSortType+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation
import MlemMiddleware

extension ApiSortType {
extension ApiSortType: @retroactive CaseIterable {
static let nonTopCases: [Self] = [
.hot,
.scaled,
Expand All @@ -34,7 +34,16 @@ extension ApiSortType {
.topAll
]

static let communitySearchCases: [Self] = [.controversial, .new, .old] + topCases
public static let allCases: [Self] = nonTopCases + topCases

enum TopSortModeFormatStyle {
case topOnly
case timescaleAbbreviated
case timescaleFull
case topAndTimescale
}

static let communitySearchCases: [Self] = [.controversial, .new, .old]
static let personSearchCases: [Self] = [.new, .old, .topAll]

var minimumVersion: SiteVersion {
Expand All @@ -45,35 +54,44 @@ extension ApiSortType {
}
}

var label: LocalizedStringResource {
private func basicLabel(abbreviateUnits: Bool = false) -> String {
switch self {
case .active: "Active"
case .hot: "Hot"
case .new: "New"
case .old: "Old"
case .topDay: "Day"
case .topWeek: "Week"
case .topMonth: "Month"
case .topYear: "Year"
case .topAll: "All Time"
case .mostComments: "Most Comments"
case .newComments: "New Comments"
case .topHour: "Hour"
case .topSixHour: "6 Hours"
case .topTwelveHour: "12 Hours"
case .topThreeMonths: "3 Months"
case .topSixMonths: "6 Months"
case .topNineMonths: "9 Months"
case .controversial: "Controversial"
case .scaled: "Scaled"
case .active:
.init(localized: "Active")
case .hot:
.init(localized: "Hot")
case .new:
.init(localized: "New")
case .old:
.init(localized: "Old")
case .topAll:
.init(localized: "All Time")
case .mostComments:
.init(localized: "Most Comments")
case .newComments:
.init(localized: "New Comments")
case .controversial:
.init(localized: "Controversial")
case .scaled:
.init(localized: "Scaled")
default:
formatter(unitsStyle: abbreviateUnits ? .abbreviated : .full)
.string(for: dateComponents)?
.capitalized ?? ""
}
}

func fullLabel(shortTopMode: Bool = false) -> String {
func label(topFormat: TopSortModeFormatStyle = .timescaleFull) -> String {
if ApiSortType.topCases.contains(self) {
return shortTopMode ? String(localized: "Top") : String(localized: "Top: \(String(localized: label))")
switch topFormat {
case .topOnly:
return String(localized: "Top")
case .topAndTimescale:
return String(localized: "Top: \(basicLabel(abbreviateUnits: true))")
default: break
}
}
return String(localized: label)
return basicLabel(abbreviateUnits: topFormat != .timescaleFull)
}

var systemImage: String {
Expand All @@ -89,4 +107,36 @@ extension ApiSortType {
default: Icons.topSort
}
}

var dateComponents: DateComponents? {
switch self {
case .topHour: .init(hour: 1)
case .topSixHour: .init(hour: 6)
case .topTwelveHour: .init(hour: 12)
case .topDay: .init(day: 1)
case .topWeek: .init(weekOfMonth: 1)
case .topMonth: .init(month: 1)
case .topThreeMonths: .init(month: 3)
case .topSixMonths: .init(month: 6)
case .topNineMonths: .init(month: 9)
case .topYear: .init(year: 1)
default: nil
}
}

var explanation: LocalizedStringResource? {
switch self {
case .hot: "Ranks posts based on the post score and creation time."
case .scaled: "Similar to \"Hot\", but ranks posts from smaller communities higher."
case .active: "Ranks posts based on the post score and the time since the last comment was created."
default: nil
}
}

private func formatter(unitsStyle: DateComponentsFormatter.UnitsStyle) -> DateComponentsFormatter {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.maximumUnitCount = 1
return formatter
}
}
Loading

0 comments on commit 45ed9d0

Please sign in to comment.