diff --git a/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents b/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents index b41a1c280..9dc908c0f 100644 --- a/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents +++ b/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -189,6 +189,7 @@ + @@ -280,7 +281,7 @@ - + diff --git a/CoreDataStack/Entity/Setting.swift b/CoreDataStack/Entity/Setting.swift index 6fac8c351..953f773fe 100644 --- a/CoreDataStack/Entity/Setting.swift +++ b/CoreDataStack/Entity/Setting.swift @@ -11,6 +11,7 @@ import Foundation public final class Setting: NSManagedObject { @NSManaged public var appearanceRaw: String + @NSManaged public var preferredTrueBlackDarkMode: Bool @NSManaged public var domain: String @NSManaged public var userID: String @@ -47,6 +48,12 @@ extension Setting { self.appearanceRaw = appearanceRaw didUpdate(at: Date()) } + + public func update(preferredTrueBlackDarkMode: Bool) { + guard preferredTrueBlackDarkMode != self.preferredTrueBlackDarkMode else { return } + self.preferredTrueBlackDarkMode = preferredTrueBlackDarkMode + didUpdate(at: Date()) + } public func didUpdate(at networkDate: Date) { self.updatedAt = networkDate diff --git a/Localization/app.json b/Localization/app.json index 114461675..a9eede0de 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -518,6 +518,11 @@ "light": "Always Light", "dark": "Always Dark" }, + "appearance_settings": { + "dark_mode": { + "title": "True black Dark Mode" + } + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 5419175b5..1a8d68a1f 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -487,6 +487,12 @@ DBCC3B9526157E6E0045B23D /* APIService+Relationship.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCC3B9426157E6E0045B23D /* APIService+Relationship.swift */; }; DBCC3B9B261584A00045B23D /* PrivateNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCC3B9A2615849F0045B23D /* PrivateNote.swift */; }; DBCCC71E25F73297007E1AB6 /* APIService+Reblog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCCC71D25F73297007E1AB6 /* APIService+Reblog.swift */; }; + DBD376A72692EA00007FEC24 /* ThemeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD376A62692EA00007FEC24 /* ThemeService.swift */; }; + DBD376AA2692EA4F007FEC24 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD376A92692EA4F007FEC24 /* Theme.swift */; }; + DBD376AC2692ECDB007FEC24 /* ThemePreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD376AB2692ECDB007FEC24 /* ThemePreference.swift */; }; + DBD376AE2692EE0A007FEC24 /* MastodonTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD376AD2692EE0A007FEC24 /* MastodonTheme.swift */; }; + DBD376B02692F20F007FEC24 /* SystemTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD376AF2692F20F007FEC24 /* SystemTheme.swift */; }; + DBD376B2269302A4007FEC24 /* UITableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD376B1269302A4007FEC24 /* UITableViewCell.swift */; }; DBD9149025DF6D8D00903DFD /* APIService+Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */; }; DBE0821525CD382600FD6BBD /* MastodonRegisterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */; }; DBE0822425CD3F1E00FD6BBD /* MastodonRegisterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE0822325CD3F1E00FD6BBD /* MastodonRegisterViewModel.swift */; }; @@ -1102,6 +1108,12 @@ DBCC3B9426157E6E0045B23D /* APIService+Relationship.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Relationship.swift"; sourceTree = ""; }; DBCC3B9A2615849F0045B23D /* PrivateNote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateNote.swift; sourceTree = ""; }; DBCCC71D25F73297007E1AB6 /* APIService+Reblog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Reblog.swift"; sourceTree = ""; }; + DBD376A62692EA00007FEC24 /* ThemeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeService.swift; sourceTree = ""; }; + DBD376A92692EA4F007FEC24 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; + DBD376AB2692ECDB007FEC24 /* ThemePreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemePreference.swift; sourceTree = ""; }; + DBD376AD2692EE0A007FEC24 /* MastodonTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonTheme.swift; sourceTree = ""; }; + DBD376AF2692F20F007FEC24 /* SystemTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemTheme.swift; sourceTree = ""; }; + DBD376B1269302A4007FEC24 /* UITableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableViewCell.swift; sourceTree = ""; }; DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Onboarding.swift"; sourceTree = ""; }; DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewController.swift; sourceTree = ""; }; DBE0822325CD3F1E00FD6BBD /* MastodonRegisterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewModel.swift; sourceTree = ""; }; @@ -1453,6 +1465,7 @@ children = ( DB45FB0425CA87B4005A8AC7 /* APIService */, DB49A61925FF327D00B98345 /* EmojiService */, + DBD376A82692EA3F007FEC24 /* ThemeService */, DB9A489B26036E19008B817C /* MastodonAttachmentService */, DB45FB0E25CA87D0005A8AC7 /* AuthenticationService.swift */, DB4563BC25E11A24004DA0B9 /* KeyboardResponderService.swift */, @@ -1969,6 +1982,7 @@ DBE54AC52636C89F004E7C0B /* NotificationPreference.swift */, DB1D842F26566512000346B3 /* KeyboardPreference.swift */, DBCBCC0C2680B908000F5B51 /* HomeTimelinePreference.swift */, + DBD376AB2692ECDB007FEC24 /* ThemePreference.swift */, ); path = Preference; sourceTree = ""; @@ -2284,6 +2298,7 @@ 2D42FF8E25C8228A004A627A /* UIButton.swift */, DB45FAD625CA6C76005A8AC7 /* UIBarButtonItem.swift */, DB4481B825EE289600BEFB67 /* UITableView.swift */, + DBD376B1269302A4007FEC24 /* UITableViewCell.swift */, 0FAA101B25E10E760017CCDE /* UIFont.swift */, 2D939AB425EDD8A90076FA61 /* String.swift */, 2D206B7F25F5F45E00143C56 /* UIImage.swift */, @@ -2593,6 +2608,17 @@ path = FetchedResultsController; sourceTree = ""; }; + DBD376A82692EA3F007FEC24 /* ThemeService */ = { + isa = PBXGroup; + children = ( + DBD376A62692EA00007FEC24 /* ThemeService.swift */, + DBD376A92692EA4F007FEC24 /* Theme.swift */, + DBD376AD2692EE0A007FEC24 /* MastodonTheme.swift */, + DBD376AF2692F20F007FEC24 /* SystemTheme.swift */, + ); + path = ThemeService; + sourceTree = ""; + }; DBE0821A25CD382900FD6BBD /* Register */ = { isa = PBXGroup; children = ( @@ -3170,6 +3196,7 @@ DB1FD45A25F27898004CFCFC /* CategoryPickerItem.swift in Sources */, DB6180F626391D580018D199 /* MediaPreviewableViewController.swift in Sources */, 2D571B2F26004EC000540450 /* NavigationBarProgressView.swift in Sources */, + DBD376AA2692EA4F007FEC24 /* Theme.swift in Sources */, 0FAA101225E105390017CCDE /* PrimaryActionButton.swift in Sources */, DB8AF53025C13561002E6C99 /* AppContext.swift in Sources */, DB92CF7225E7BB98002C1017 /* PollOptionTableViewCell.swift in Sources */, @@ -3430,6 +3457,7 @@ DB447691260B406600B66B82 /* CustomEmojiPickerItemCollectionViewCell.swift in Sources */, DB9282B225F3222800823B15 /* PickServerEmptyStateView.swift in Sources */, DB1FD45025F26FA1004CFCFC /* MastodonPickServerViewModel+Diffable.swift in Sources */, + DBD376AC2692ECDB007FEC24 /* ThemePreference.swift in Sources */, DB2B3AE925E38850007045F9 /* UIViewPreview.swift in Sources */, DB68046C2636DC9E00430867 /* MastodonNotification.swift in Sources */, DBAE3F9E2616E308004B8251 /* APIService+Mute.swift in Sources */, @@ -3475,6 +3503,7 @@ 5DFC35DF262068D20045711D /* SearchViewController+Follow.swift in Sources */, DB8AF52E25C13561002E6C99 /* ViewStateStore.swift in Sources */, 2DA7D04A25CA52CB00804E11 /* TimelineBottomLoaderTableViewCell.swift in Sources */, + DBD376B2269302A4007FEC24 /* UITableViewCell.swift in Sources */, DBAC6499267DF2C4007FE9FD /* TimelineBottomLoaderNode.swift in Sources */, 2D76318325C14E8F00929FB9 /* PublicTimelineViewModel+Diffable.swift in Sources */, DBBF1DBF2652401B00E5B703 /* AutoCompleteViewModel.swift in Sources */, @@ -3510,9 +3539,12 @@ DB9D6BFF25E4F5940051B173 /* ProfileViewController.swift in Sources */, 0FB3D30825E524C600AAD544 /* PickServerCategoriesCell.swift in Sources */, 2D4AD8A226316CD200613EFC /* SelectedAccountSection.swift in Sources */, + DBD376A72692EA00007FEC24 /* ThemeService.swift in Sources */, + DBD376AE2692EE0A007FEC24 /* MastodonTheme.swift in Sources */, DB789A1225F9F2CC0071ACA0 /* ComposeViewModel.swift in Sources */, DBB525362611ECEB002F1F29 /* UserTimelineViewController.swift in Sources */, DB6D1B3D2636857500ACB481 /* AppearancePreference.swift in Sources */, + DBD376B02692F20F007FEC24 /* SystemTheme.swift in Sources */, DB938F3326243D6200E5B6C1 /* TimelineTopLoaderTableViewCell.swift in Sources */, DB3667A4268AE2370027D07F /* ComposeStatusPollTableViewCell.swift in Sources */, DBBF1DC226524D2900E5B703 /* AutoCompleteTableViewCell.swift in Sources */, diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index f5353ed3d..2fe360475 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -12,7 +12,7 @@ CoreDataStack.xcscheme_^#shared#^_ orderHint - 19 + 27 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -37,7 +37,7 @@ NotificationService.xcscheme_^#shared#^_ orderHint - 18 + 26 SuppressBuildableAutocreation diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index fbe0ced5c..310a819b5 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -280,6 +280,7 @@ private extension SceneCoordinator { return nil } let _viewController = SFSafariViewController(url: url) + _viewController.preferredBarTintColor = ThemeService.shared.currentTheme.value.navigationBarBackgroundColor _viewController.preferredControlTintColor = Asset.Colors.brandBlue.color viewController = _viewController diff --git a/Mastodon/Diffiable/Item/PollItem.swift b/Mastodon/Diffiable/Item/PollItem.swift index 1e7bd4ce7..0622e1d32 100644 --- a/Mastodon/Diffiable/Item/PollItem.swift +++ b/Mastodon/Diffiable/Item/PollItem.swift @@ -10,7 +10,7 @@ import CoreData /// Note: update Equatable when change case enum PollItem { - case opion(objectID: NSManagedObjectID, attribute: Attribute) + case option(objectID: NSManagedObjectID, attribute: Attribute) } @@ -51,7 +51,7 @@ extension PollItem { extension PollItem: Equatable { static func == (lhs: PollItem, rhs: PollItem) -> Bool { switch (lhs, rhs) { - case (.opion(let objectIDLeft, _), .opion(let objectIDRight, _)): + case (.option(let objectIDLeft, _), .option(let objectIDRight, _)): return objectIDLeft == objectIDRight } } @@ -61,7 +61,7 @@ extension PollItem: Equatable { extension PollItem: Hashable { func hash(into hasher: inout Hasher) { switch self { - case .opion(let objectID, _): + case .option(let objectID, _): hasher.combine(objectID) } } diff --git a/Mastodon/Diffiable/Item/SettingsItem.swift b/Mastodon/Diffiable/Item/SettingsItem.swift index e81d7b599..f21dea31c 100644 --- a/Mastodon/Diffiable/Item/SettingsItem.swift +++ b/Mastodon/Diffiable/Item/SettingsItem.swift @@ -10,6 +10,7 @@ import CoreData enum SettingsItem: Hashable { case appearance(settingObjectID: NSManagedObjectID) + case appearanceDarkMode(settingObjectID: NSManagedObjectID) case notification(settingObjectID: NSManagedObjectID, switchMode: NotificationSwitchMode) case boringZone(item: Link) case spicyZone(item: Link) diff --git a/Mastodon/Diffiable/Section/PollSection.swift b/Mastodon/Diffiable/Section/PollSection.swift index 581620c0c..872cc7aea 100644 --- a/Mastodon/Diffiable/Section/PollSection.swift +++ b/Mastodon/Diffiable/Section/PollSection.swift @@ -32,7 +32,7 @@ extension PollSection { ) -> UITableViewDiffableDataSource { return UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in switch item { - case .opion(let objectID, let attribute): + case .option(let objectID, let attribute): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PollOptionTableViewCell.self), for: indexPath) as! PollOptionTableViewCell managedObjectContext.performAndWait { let option = managedObjectContext.object(with: objectID) as! PollOption @@ -67,13 +67,25 @@ extension PollSection { cell.pollOptionView.checkmarkBackgroundView.isHidden = true cell.pollOptionView.checkmarkImageView.isHidden = true case .off: - cell.pollOptionView.checkmarkBackgroundView.backgroundColor = Asset.Colors.Background.tertiarySystemBackground.color - cell.pollOptionView.checkmarkBackgroundView.layer.borderColor = Asset.Colors.Background.Cell.highlight.color.withAlphaComponent(0.3).cgColor + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak cell] theme in + guard let cell = cell else { return } + cell.pollOptionView.checkmarkBackgroundView.backgroundColor = theme.tertiarySystemBackgroundColor + cell.pollOptionView.checkmarkBackgroundView.layer.borderColor = theme.tableViewCellSelectionBackgroundColor.withAlphaComponent(0.3).cgColor + } + .store(in: &cell.disposeBag) cell.pollOptionView.checkmarkBackgroundView.layer.borderWidth = 1 cell.pollOptionView.checkmarkBackgroundView.isHidden = false cell.pollOptionView.checkmarkImageView.isHidden = true case .on: - cell.pollOptionView.checkmarkBackgroundView.backgroundColor = Asset.Colors.Background.tertiarySystemBackground.color + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak cell] theme in + guard let cell = cell else { return } + cell.pollOptionView.checkmarkBackgroundView.backgroundColor = theme.tertiarySystemBackgroundColor + } + .store(in: &cell.disposeBag) cell.pollOptionView.checkmarkBackgroundView.layer.borderColor = UIColor.clear.cgColor cell.pollOptionView.checkmarkBackgroundView.layer.borderWidth = 0 cell.pollOptionView.checkmarkBackgroundView.isHidden = false diff --git a/Mastodon/Diffiable/Section/SettingsSection.swift b/Mastodon/Diffiable/Section/SettingsSection.swift index 6079d90d3..9a248dca3 100644 --- a/Mastodon/Diffiable/Section/SettingsSection.swift +++ b/Mastodon/Diffiable/Section/SettingsSection.swift @@ -9,16 +9,18 @@ import Foundation enum SettingsSection: Hashable { case appearance + case appearanceSettings case notifications case boringZone case spicyZone var title: String { switch self { - case .appearance: return L10n.Scene.Settings.Section.Appearance.title - case .notifications: return L10n.Scene.Settings.Section.Notifications.title - case .boringZone: return L10n.Scene.Settings.Section.Boringzone.title - case .spicyZone: return L10n.Scene.Settings.Section.Spicyzone.title + case .appearance: return L10n.Scene.Settings.Section.Appearance.title + case .appearanceSettings: return "" + case .notifications: return L10n.Scene.Settings.Section.Notifications.title + case .boringZone: return L10n.Scene.Settings.Section.Boringzone.title + case .spicyZone: return L10n.Scene.Settings.Section.Spicyzone.title } } } diff --git a/Mastodon/Diffiable/Section/StatusSection.swift b/Mastodon/Diffiable/Section/StatusSection.swift index ef6e14223..50e084529 100644 --- a/Mastodon/Diffiable/Section/StatusSection.swift +++ b/Mastodon/Diffiable/Section/StatusSection.swift @@ -913,7 +913,7 @@ extension StatusSection { }() return PollItem.Attribute(selectState: selectState, voteState: voteState) }() - let option = PollItem.opion(objectID: option.objectID, attribute: attribute) + let option = PollItem.option(objectID: option.objectID, attribute: attribute) return option } snapshot.appendItems(pollItems, toSection: .main) diff --git a/Mastodon/Extension/UITableViewCell.swift b/Mastodon/Extension/UITableViewCell.swift new file mode 100644 index 000000000..1ef13877d --- /dev/null +++ b/Mastodon/Extension/UITableViewCell.swift @@ -0,0 +1,22 @@ +// +// UITableViewCell.swift +// Mastodon +// +// Created by MainasuK Cirno on 2021-7-5. +// + +import UIKit + +extension UITableViewCell { + + /// The color of the cell when it is selected. + @objc dynamic var selectionColor: UIColor? { + get { return selectedBackgroundView?.backgroundColor } + set { + guard selectionStyle != .none else { return } + let view = UIView() + view.backgroundColor = newValue + selectedBackgroundView = view + } + } +} diff --git a/Mastodon/Extension/UIView.swift b/Mastodon/Extension/UIView.swift index 50dd08f17..85d8112c1 100644 --- a/Mastodon/Extension/UIView.swift +++ b/Mastodon/Extension/UIView.swift @@ -14,7 +14,7 @@ extension UIView { UIColor(dynamicProvider: { collection in switch collection.userInterfaceStyle { case .dark: - return Asset.Colors.Background.Cell.separator.color + return ThemeService.shared.currentTheme.value.separator default: return .separator } diff --git a/Mastodon/Generated/Assets.swift b/Mastodon/Generated/Assets.swift index 376ea4b4e..dc93361c2 100644 --- a/Mastodon/Generated/Assets.swift +++ b/Mastodon/Generated/Assets.swift @@ -32,15 +32,10 @@ internal enum Asset { } internal enum Colors { internal enum Background { - internal enum Cell { - internal static let highlight = ColorAsset(name: "Colors/Background/Cell/highlight") - internal static let separator = ColorAsset(name: "Colors/Background/Cell/separator") - } internal enum Poll { internal static let disabled = ColorAsset(name: "Colors/Background/Poll/disabled") } internal static let alertYellow = ColorAsset(name: "Colors/Background/alert.yellow") - internal static let bar = ColorAsset(name: "Colors/Background/bar") internal static let dangerBorder = ColorAsset(name: "Colors/Background/danger.border") internal static let danger = ColorAsset(name: "Colors/Background/danger") internal static let mediaTypeIndicotor = ColorAsset(name: "Colors/Background/media.type.indicotor") @@ -64,9 +59,6 @@ internal enum Asset { internal static let disabled = ColorAsset(name: "Colors/Button/disabled") internal static let inactive = ColorAsset(name: "Colors/Button/inactive") } - internal enum ContentWarningOverlay { - internal static let background = ColorAsset(name: "Colors/ContentWarningOverlay/background") - } internal enum Icon { internal static let plus = ColorAsset(name: "Colors/Icon/plus") } @@ -141,6 +133,42 @@ internal enum Asset { internal static let appearanceDark = ImageAsset(name: "Settings/appearance.dark") internal static let appearanceLight = ImageAsset(name: "Settings/appearance.light") } + internal enum Theme { + internal enum Mastodon { + internal static let contentWarningOverlayBackground = ColorAsset(name: "Theme/Mastodon/content.warning.overlay.background") + internal static let navigationBarBackground = ColorAsset(name: "Theme/Mastodon/navigation.bar.background") + internal static let profileFieldCollectionViewBackground = ColorAsset(name: "Theme/Mastodon/profile.field.collection.view.background") + internal static let secondaryGroupedSystemBackground = ColorAsset(name: "Theme/Mastodon/secondary.grouped.system.background") + internal static let secondarySystemBackground = ColorAsset(name: "Theme/Mastodon/secondary.system.background") + internal static let systemBackground = ColorAsset(name: "Theme/Mastodon/system.background") + internal static let systemElevatedBackground = ColorAsset(name: "Theme/Mastodon/system.elevated.background") + internal static let systemGroupedBackground = ColorAsset(name: "Theme/Mastodon/system.grouped.background") + internal static let tabBarBackground = ColorAsset(name: "Theme/Mastodon/tab.bar.background") + internal static let tableViewCellBackground = ColorAsset(name: "Theme/Mastodon/table.view.cell.background") + internal static let tableViewCellSelectionBackground = ColorAsset(name: "Theme/Mastodon/table.view.cell.selection.background") + internal static let tertiarySystemBackground = ColorAsset(name: "Theme/Mastodon/tertiary.system.background") + internal static let tertiarySystemGroupedBackground = ColorAsset(name: "Theme/Mastodon/tertiary.system.grouped.background") + internal static let separator = ColorAsset(name: "Theme/Mastodon/separator") + internal static let tabBarItemInactiveIconColor = ColorAsset(name: "Theme/Mastodon/tab.bar.item.inactive.icon.color") + } + internal enum System { + internal static let contentWarningOverlayBackground = ColorAsset(name: "Theme/System/content.warning.overlay.background") + internal static let navigationBarBackground = ColorAsset(name: "Theme/System/navigation.bar.background") + internal static let profileFieldCollectionViewBackground = ColorAsset(name: "Theme/System/profile.field.collection.view.background") + internal static let secondaryGroupedSystemBackground = ColorAsset(name: "Theme/System/secondary.grouped.system.background") + internal static let secondarySystemBackground = ColorAsset(name: "Theme/System/secondary.system.background") + internal static let systemBackground = ColorAsset(name: "Theme/System/system.background") + internal static let systemElevatedBackground = ColorAsset(name: "Theme/System/system.elevated.background") + internal static let systemGroupedBackground = ColorAsset(name: "Theme/System/system.grouped.background") + internal static let tabBarBackground = ColorAsset(name: "Theme/System/tab.bar.background") + internal static let tableViewCellBackground = ColorAsset(name: "Theme/System/table.view.cell.background") + internal static let tableViewCellSelectionBackground = ColorAsset(name: "Theme/System/table.view.cell.selection.background") + internal static let tertiarySystemBackground = ColorAsset(name: "Theme/System/tertiary.system.background") + internal static let tertiarySystemGroupedBackground = ColorAsset(name: "Theme/System/tertiary.system.grouped.background") + internal static let separator = ColorAsset(name: "Theme/System/separator") + internal static let tabBarItemInactiveIconColor = ColorAsset(name: "Theme/System/tab.bar.item.inactive.icon.color") + } + } } // swiftlint:enable identifier_name line_length nesting type_body_length type_name diff --git a/Mastodon/Generated/Strings.swift b/Mastodon/Generated/Strings.swift index caa5bcce5..e34ec45f5 100644 --- a/Mastodon/Generated/Strings.swift +++ b/Mastodon/Generated/Strings.swift @@ -965,6 +965,12 @@ internal enum L10n { /// Appearance internal static let title = L10n.tr("Localizable", "Scene.Settings.Section.Appearance.Title") } + internal enum AppearanceSettings { + internal enum DarkMode { + /// True black Dark Mode + internal static let title = L10n.tr("Localizable", "Scene.Settings.Section.AppearanceSettings.DarkMode.Title") + } + } internal enum Boringzone { /// Privacy Policy internal static let privacy = L10n.tr("Localizable", "Scene.Settings.Section.Boringzone.Privacy") diff --git a/Mastodon/Preference/ThemePreference.swift b/Mastodon/Preference/ThemePreference.swift new file mode 100644 index 000000000..5faf6097c --- /dev/null +++ b/Mastodon/Preference/ThemePreference.swift @@ -0,0 +1,20 @@ +// +// ThemePreference.swift +// Mastodon +// +// Created by MainasuK Cirno on 2021-7-5. +// + +import UIKit + +extension UserDefaults { + + @objc dynamic var currentThemeNameRawValue: String { + get { + register(defaults: [#function: ThemeName.mastodon.rawValue]) + return string(forKey: #function) ?? ThemeName.mastodon.rawValue + } + set { self[#function] = newValue } + } + +} diff --git a/Mastodon/Protocol/StatusProvider/StatusProvider+StatusTableViewCellDelegate.swift b/Mastodon/Protocol/StatusProvider/StatusProvider+StatusTableViewCellDelegate.swift index 2803113dd..a752f2180 100644 --- a/Mastodon/Protocol/StatusProvider/StatusProvider+StatusTableViewCellDelegate.swift +++ b/Mastodon/Protocol/StatusProvider/StatusProvider+StatusTableViewCellDelegate.swift @@ -137,7 +137,7 @@ extension StatusTableViewCellDelegate where Self: StatusProvider { guard let diffableDataSource = cell.statusView.pollTableViewDataSource else { return } let item = diffableDataSource.itemIdentifier(for: indexPath) - guard case let .opion(objectID, _) = item else { return } + guard case let .option(objectID, _) = item else { return } guard let option = managedObjectContext.object(with: objectID) as? PollOption else { return } let poll = option.poll diff --git a/Mastodon/Resources/Assets.xcassets/Colors/Slider/track.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Colors/Slider/track.colorset/Contents.json index 1c84ad477..ccbeb8648 100644 --- a/Mastodon/Resources/Assets.xcassets/Colors/Slider/track.colorset/Contents.json +++ b/Mastodon/Resources/Assets.xcassets/Colors/Slider/track.colorset/Contents.json @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "0.300", - "blue" : "1.000", - "green" : "1.000", - "red" : "1.000" + "blue" : "60", + "green" : "60", + "red" : "60" } }, "idiom" : "universal" diff --git a/Mastodon/Resources/Assets.xcassets/Colors/Background/Cell/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Contents.json similarity index 100% rename from Mastodon/Resources/Assets.xcassets/Colors/Background/Cell/Contents.json rename to Mastodon/Resources/Assets.xcassets/Theme/Contents.json diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/content.warning.overlay.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/content.warning.overlay.background.colorset/Contents.json new file mode 100644 index 000000000..485b4813a --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/content.warning.overlay.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.922", + "green" : "0.898", + "red" : "0.867" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.263", + "green" : "0.208", + "red" : "0.192" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/navigation.bar.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/navigation.bar.background.colorset/Contents.json new file mode 100644 index 000000000..ec7c19fac --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/navigation.bar.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.940", + "blue" : "0.976", + "green" : "0.976", + "red" : "0.976" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "67", + "green" : "53", + "red" : "49" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/profile.field.collection.view.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/profile.field.collection.view.background.colorset/Contents.json new file mode 100644 index 000000000..5e9b0d486 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/profile.field.collection.view.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/secondary.grouped.system.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/secondary.grouped.system.background.colorset/Contents.json new file mode 100644 index 000000000..ef6c7f7b1 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/secondary.grouped.system.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.996", + "green" : "1.000", + "red" : "0.996" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.263", + "green" : "0.208", + "red" : "0.192" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/secondary.system.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/secondary.system.background.colorset/Contents.json new file mode 100644 index 000000000..c915c8911 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/secondary.system.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.910", + "green" : "0.882", + "red" : "0.851" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.133", + "green" : "0.106", + "red" : "0.098" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/system.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/system.background.colorset/Contents.json new file mode 100644 index 000000000..4572c2409 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/system.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.996", + "green" : "1.000", + "red" : "0.996" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.216", + "green" : "0.173", + "red" : "0.157" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Colors/ContentWarningOverlay/background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/system.elevated.background.colorset/Contents.json similarity index 77% rename from Mastodon/Resources/Assets.xcassets/Colors/ContentWarningOverlay/background.colorset/Contents.json rename to Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/system.elevated.background.colorset/Contents.json index 009d3156b..dd6cbfd91 100644 --- a/Mastodon/Resources/Assets.xcassets/Colors/ContentWarningOverlay/background.colorset/Contents.json +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/system.elevated.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "235", - "green" : "229", - "red" : "221" + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" } }, "idiom" : "universal" @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0x43", - "green" : "0x35", - "red" : "0x31" + "blue" : "55", + "green" : "44", + "red" : "40" } }, "idiom" : "universal" diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/system.grouped.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/system.grouped.background.colorset/Contents.json new file mode 100644 index 000000000..c915c8911 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/system.grouped.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.910", + "green" : "0.882", + "red" : "0.851" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.133", + "green" : "0.106", + "red" : "0.098" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Colors/Background/bar.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/tab.bar.background.colorset/Contents.json similarity index 88% rename from Mastodon/Resources/Assets.xcassets/Colors/Background/bar.colorset/Contents.json rename to Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/tab.bar.background.colorset/Contents.json index c3ec51c83..e3ffa5a61 100644 --- a/Mastodon/Resources/Assets.xcassets/Colors/Background/bar.colorset/Contents.json +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/tab.bar.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "0.940", - "blue" : "249", - "green" : "249", - "red" : "249" + "blue" : "0.976", + "green" : "0.976", + "red" : "0.976" } }, "idiom" : "universal" diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/table.view.cell.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/table.view.cell.background.colorset/Contents.json new file mode 100644 index 000000000..e2f09e3c5 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/table.view.cell.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.263", + "green" : "0.208", + "red" : "0.192" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Colors/Background/Cell/highlight.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/table.view.cell.selection.background.colorset/Contents.json similarity index 88% rename from Mastodon/Resources/Assets.xcassets/Colors/Background/Cell/highlight.colorset/Contents.json rename to Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/table.view.cell.selection.background.colorset/Contents.json index da756e551..91b8281dc 100644 --- a/Mastodon/Resources/Assets.xcassets/Colors/Background/Cell/highlight.colorset/Contents.json +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/table.view.cell.selection.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "214", - "green" : "209", - "red" : "209" + "blue" : "235", + "green" : "229", + "red" : "221" } }, "idiom" : "universal" diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/tertiary.system.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/tertiary.system.background.colorset/Contents.json new file mode 100644 index 000000000..4572c2409 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/tertiary.system.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.996", + "green" : "1.000", + "red" : "0.996" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.216", + "green" : "0.173", + "red" : "0.157" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/tertiary.system.grouped.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/tertiary.system.grouped.background.colorset/Contents.json new file mode 100644 index 000000000..98dd7bbde --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Background/tertiary.system.grouped.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.910", + "green" : "0.882", + "red" : "0.851" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.263", + "green" : "0.208", + "red" : "0.192" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Colors/ContentWarningOverlay/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Contents.json similarity index 100% rename from Mastodon/Resources/Assets.xcassets/Colors/ContentWarningOverlay/Contents.json rename to Mastodon/Resources/Assets.xcassets/Theme/Mastodon/Contents.json diff --git a/Mastodon/Resources/Assets.xcassets/Colors/Background/Cell/separator.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/separator.colorset/Contents.json similarity index 100% rename from Mastodon/Resources/Assets.xcassets/Colors/Background/Cell/separator.colorset/Contents.json rename to Mastodon/Resources/Assets.xcassets/Theme/Mastodon/separator.colorset/Contents.json diff --git a/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/tab.bar.item.inactive.icon.color.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/tab.bar.item.inactive.icon.color.colorset/Contents.json new file mode 100644 index 000000000..1accfacdf --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/Mastodon/tab.bar.item.inactive.icon.color.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.549", + "green" : "0.510", + "red" : "0.431" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "200", + "green" : "174", + "red" : "155" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/content.warning.overlay.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/content.warning.overlay.background.colorset/Contents.json new file mode 100644 index 000000000..485b4813a --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/content.warning.overlay.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.922", + "green" : "0.898", + "red" : "0.867" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.263", + "green" : "0.208", + "red" : "0.192" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/navigation.bar.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/navigation.bar.background.colorset/Contents.json new file mode 100644 index 000000000..7f9578a7a --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/navigation.bar.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.940", + "blue" : "249", + "green" : "249", + "red" : "249" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.940", + "blue" : "29", + "green" : "29", + "red" : "29" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/profile.field.collection.view.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/profile.field.collection.view.background.colorset/Contents.json new file mode 100644 index 000000000..82edd034b --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/profile.field.collection.view.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "30", + "green" : "28", + "red" : "28" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/secondary.grouped.system.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/secondary.grouped.system.background.colorset/Contents.json new file mode 100644 index 000000000..036066700 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/secondary.grouped.system.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.996", + "green" : "1.000", + "red" : "0.996" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "46", + "green" : "44", + "red" : "44" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json new file mode 100644 index 000000000..b9a69ec7d --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.910", + "green" : "0.882", + "red" : "0.851" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "46", + "green" : "44", + "red" : "44" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.background.colorset/Contents.json new file mode 100644 index 000000000..2b3ad55ea --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.996", + "green" : "1.000", + "red" : "0.996" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.elevated.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.elevated.background.colorset/Contents.json new file mode 100644 index 000000000..ca11ee759 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.elevated.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.118", + "green" : "0.110", + "red" : "0.110" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json new file mode 100644 index 000000000..370a745eb --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.910", + "green" : "0.882", + "red" : "0.851" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/tab.bar.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/tab.bar.background.colorset/Contents.json new file mode 100644 index 000000000..8ef5fd6db --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/tab.bar.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.940", + "blue" : "0.976", + "green" : "0.976", + "red" : "0.976" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.940", + "blue" : "0.114", + "green" : "0.114", + "red" : "0.114" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/table.view.cell.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/table.view.cell.background.colorset/Contents.json new file mode 100644 index 000000000..6b983510e --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/table.view.cell.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0", + "green" : "0", + "red" : "0" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/table.view.cell.selection.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/table.view.cell.selection.background.colorset/Contents.json new file mode 100644 index 000000000..d211d7df9 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/table.view.cell.selection.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.922", + "green" : "0.898", + "red" : "0.867" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "60", + "green" : "58", + "red" : "58" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/tertiary.system.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/tertiary.system.background.colorset/Contents.json new file mode 100644 index 000000000..e7d7e3cd0 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/tertiary.system.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.996", + "green" : "1.000", + "red" : "0.996" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "60", + "green" : "58", + "red" : "58" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/tertiary.system.grouped.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/tertiary.system.grouped.background.colorset/Contents.json new file mode 100644 index 000000000..ab65a98ec --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/tertiary.system.grouped.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.910", + "green" : "0.882", + "red" : "0.851" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "60", + "green" : "58", + "red" : "58" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Contents.json new file mode 100644 index 000000000..6e965652d --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/separator.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/separator.colorset/Contents.json new file mode 100644 index 000000000..04fbae35d --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/separator.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.290", + "blue" : "0x43", + "green" : "0x3C", + "red" : "0x3C" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.650", + "blue" : "0x58", + "green" : "0x54", + "red" : "0x54" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/tab.bar.item.inactive.icon.color.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/tab.bar.item.inactive.icon.color.colorset/Contents.json new file mode 100644 index 000000000..ece9000aa --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/tab.bar.item.inactive.icon.color.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.549", + "green" : "0.510", + "red" : "0.431" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "140", + "green" : "130", + "red" : "110" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/ar.lproj/Localizable.strings b/Mastodon/Resources/ar.lproj/Localizable.strings index 71e475106..3e2394724 100644 --- a/Mastodon/Resources/ar.lproj/Localizable.strings +++ b/Mastodon/Resources/ar.lproj/Localizable.strings @@ -324,6 +324,7 @@ any server."; "Scene.Settings.Section.Appearance.Dark" = "Always Dark"; "Scene.Settings.Section.Appearance.Light" = "Always Light"; "Scene.Settings.Section.Appearance.Title" = "Appearance"; +"Scene.Settings.Section.AppearanceSettings.DarkMode.Title" = "True black Dark Mode"; "Scene.Settings.Section.Boringzone.Privacy" = "Privacy Policy"; "Scene.Settings.Section.Boringzone.Terms" = "Terms of Service"; "Scene.Settings.Section.Boringzone.Title" = "The Boring zone"; diff --git a/Mastodon/Resources/en.lproj/Localizable.strings b/Mastodon/Resources/en.lproj/Localizable.strings index 71e475106..3e2394724 100644 --- a/Mastodon/Resources/en.lproj/Localizable.strings +++ b/Mastodon/Resources/en.lproj/Localizable.strings @@ -324,6 +324,7 @@ any server."; "Scene.Settings.Section.Appearance.Dark" = "Always Dark"; "Scene.Settings.Section.Appearance.Light" = "Always Light"; "Scene.Settings.Section.Appearance.Title" = "Appearance"; +"Scene.Settings.Section.AppearanceSettings.DarkMode.Title" = "True black Dark Mode"; "Scene.Settings.Section.Boringzone.Privacy" = "Privacy Policy"; "Scene.Settings.Section.Boringzone.Terms" = "Terms of Service"; "Scene.Settings.Section.Boringzone.Title" = "The Boring zone"; diff --git a/Mastodon/Scene/Compose/AutoComplete/AutoCompleteViewController.swift b/Mastodon/Scene/Compose/AutoComplete/AutoCompleteViewController.swift index 56832b9bf..6b71c5dd2 100644 --- a/Mastodon/Scene/Compose/AutoComplete/AutoCompleteViewController.swift +++ b/Mastodon/Scene/Compose/AutoComplete/AutoCompleteViewController.swift @@ -25,7 +25,7 @@ final class AutoCompleteViewController: UIViewController { let chevronView = AutoCompleteTopChevronView() let containerBackgroundView: UIView = { let view = UIView() - view.backgroundColor = Asset.Colors.Background.systemBackground.color + view.backgroundColor = ThemeService.shared.currentTheme.value.systemBackgroundColor return view }() diff --git a/Mastodon/Scene/Compose/AutoComplete/Cell/AutoCompleteTableViewCell.swift b/Mastodon/Scene/Compose/AutoComplete/Cell/AutoCompleteTableViewCell.swift index f150dd754..65044f95f 100644 --- a/Mastodon/Scene/Compose/AutoComplete/Cell/AutoCompleteTableViewCell.swift +++ b/Mastodon/Scene/Compose/AutoComplete/Cell/AutoCompleteTableViewCell.swift @@ -73,13 +73,6 @@ final class AutoCompleteTableViewCell: UITableViewCell { extension AutoCompleteTableViewCell { private func _init() { - backgroundColor = .clear - selectedBackgroundView = { - let view = UIView() - view.backgroundColor = Asset.Colors.Background.Cell.highlight.color - return view - }() - let topPaddingView = UIView() let bottomPaddingView = UIView() diff --git a/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusAttachmentCollectionViewCell.swift b/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusAttachmentCollectionViewCell.swift index 0fa9319d3..a5906a9da 100644 --- a/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusAttachmentCollectionViewCell.swift +++ b/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusAttachmentCollectionViewCell.swift @@ -86,10 +86,10 @@ extension ComposeStatusAttachmentCollectionViewCell { removeButton.widthAnchor.constraint(equalToConstant: ComposeStatusAttachmentCollectionViewCell.removeButtonSize.width).priority(.defaultHigh), removeButton.heightAnchor.constraint(equalToConstant: ComposeStatusAttachmentCollectionViewCell.removeButtonSize.height).priority(.defaultHigh), ]) - + removeButton.addTarget(self, action: #selector(ComposeStatusAttachmentCollectionViewCell.removeButtonDidPressed(_:)), for: .touchUpInside) } - + } diff --git a/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionAppendEntryCollectionViewCell.swift b/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionAppendEntryCollectionViewCell.swift index 4827c16f7..7c8a6135f 100644 --- a/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionAppendEntryCollectionViewCell.swift +++ b/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionAppendEntryCollectionViewCell.swift @@ -29,7 +29,7 @@ final class ComposeStatusPollOptionAppendEntryCollectionViewCell: UICollectionVi override var isHighlighted: Bool { didSet { - pollOptionView.roundedBackgroundView.backgroundColor = isHighlighted ? Asset.Colors.Background.tertiarySystemBackground.color : Asset.Colors.Background.secondarySystemBackground.color + pollOptionView.roundedBackgroundView.backgroundColor = isHighlighted ? ThemeService.shared.currentTheme.value.tertiarySystemGroupedBackgroundColor.withAlphaComponent(0.6) : ThemeService.shared.currentTheme.value.tertiarySystemGroupedBackgroundColor pollOptionView.plusCircleImageView.tintColor = isHighlighted ? Asset.Colors.brandBlue.color.withAlphaComponent(0.5) : Asset.Colors.brandBlue.color } } @@ -82,7 +82,7 @@ extension ComposeStatusPollOptionAppendEntryCollectionViewCell { pollOptionView.optionTextField.isHidden = true pollOptionView.plusCircleImageView.isHidden = false - pollOptionView.roundedBackgroundView.backgroundColor = Asset.Colors.Background.secondarySystemBackground.color + pollOptionView.roundedBackgroundView.backgroundColor = ThemeService.shared.currentTheme.value.tertiarySystemGroupedBackgroundColor setupBorderColor() pollOptionView.addGestureRecognizer(singleTagGestureRecognizer) @@ -93,7 +93,7 @@ extension ComposeStatusPollOptionAppendEntryCollectionViewCell { private func setupBorderColor() { pollOptionView.roundedBackgroundView.layer.borderWidth = 1 - pollOptionView.roundedBackgroundView.layer.borderColor = Asset.Colors.Background.secondarySystemBackground.color.cgColor + pollOptionView.roundedBackgroundView.layer.borderColor = ThemeService.shared.currentTheme.value.tableViewCellSelectionBackgroundColor.withAlphaComponent(0.3).cgColor } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { diff --git a/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionCollectionViewCell.swift b/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionCollectionViewCell.swift index ab2117f13..ae90cd7b6 100644 --- a/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionCollectionViewCell.swift +++ b/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionCollectionViewCell.swift @@ -83,9 +83,11 @@ extension ComposeStatusPollOptionCollectionViewCell { pollOptionView.checkmarkImageView.isHidden = true pollOptionView.optionPercentageLabel.isHidden = true pollOptionView.optionTextField.text = nil - - pollOptionView.roundedBackgroundView.backgroundColor = Asset.Colors.Background.secondarySystemBackground.color - pollOptionView.checkmarkBackgroundView.backgroundColor = Asset.Colors.Background.tertiarySystemBackground.color + + pollOptionView.roundedBackgroundView.backgroundColor = ThemeService.shared.currentTheme.value.tertiarySystemGroupedBackgroundColor + pollOptionView.checkmarkBackgroundView.backgroundColor = UIColor(dynamicProvider: { traitCollection in + return traitCollection.userInterfaceStyle == .light ? .white : ThemeService.shared.currentTheme.value.tableViewCellSelectionBackgroundColor + }) setupBorderColor() pollOptionView.addGestureRecognizer(singleTagGestureRecognizer) @@ -103,7 +105,10 @@ extension ComposeStatusPollOptionCollectionViewCell { } private func setupBorderColor() { - pollOptionView.checkmarkBackgroundView.layer.borderColor = UIColor.systemGray3.cgColor + pollOptionView.roundedBackgroundView.layer.borderWidth = 1 + pollOptionView.roundedBackgroundView.layer.borderColor = ThemeService.shared.currentTheme.value.tableViewCellSelectionBackgroundColor.withAlphaComponent(0.3).cgColor + + pollOptionView.checkmarkBackgroundView.layer.borderColor = ThemeService.shared.currentTheme.value.tableViewCellSelectionBackgroundColor.withAlphaComponent(0.3).cgColor pollOptionView.checkmarkBackgroundView.layer.borderWidth = 1 } diff --git a/Mastodon/Scene/Compose/ComposeViewController.swift b/Mastodon/Scene/Compose/ComposeViewController.swift index 2d0c7f4c1..a3c56b3e2 100644 --- a/Mastodon/Scene/Compose/ComposeViewController.swift +++ b/Mastodon/Scene/Compose/ComposeViewController.swift @@ -53,7 +53,6 @@ final class ComposeViewController: UIViewController, NeedsDependency { tableView.register(ComposeRepliedToStatusContentTableViewCell.self, forCellReuseIdentifier: String(describing: ComposeRepliedToStatusContentTableViewCell.self)) tableView.register(ComposeStatusContentTableViewCell.self, forCellReuseIdentifier: String(describing: ComposeStatusContentTableViewCell.self)) tableView.register(ComposeStatusAttachmentTableViewCell.self, forCellReuseIdentifier: String(describing: ComposeStatusAttachmentTableViewCell.self)) - tableView.backgroundColor = Asset.Scene.Compose.background.color tableView.alwaysBounceVertical = true tableView.separatorStyle = .none tableView.tableFooterView = UIView() @@ -145,7 +144,15 @@ extension ComposeViewController { self.title = title } .store(in: &disposeBag) - view.backgroundColor = Asset.Scene.Compose.background.color + view.backgroundColor = ThemeService.shared.currentTheme.value.systemElevatedBackgroundColor + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.systemElevatedBackgroundColor + self.tableView.backgroundColor = theme.systemElevatedBackgroundColor + } + .store(in: &disposeBag) navigationItem.leftBarButtonItem = cancelBarButtonItem navigationItem.rightBarButtonItem = publishBarButtonItem publishButton.addTarget(self, action: #selector(ComposeViewController.publishBarButtonItemPressed(_:)), for: .touchUpInside) @@ -903,7 +910,7 @@ extension ComposeViewController: UICollectionViewDelegate { extension ComposeViewController: UIAdaptivePresentationControllerDelegate { func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { - return .fullScreen + return traitCollection.userInterfaceIdiom == .pad ? .formSheet : .automatic } func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { diff --git a/Mastodon/Scene/Compose/TableViewCell/ComposeStatusAttachmentTableViewCell.swift b/Mastodon/Scene/Compose/TableViewCell/ComposeStatusAttachmentTableViewCell.swift index cb4da5765..f8d2bcf32 100644 --- a/Mastodon/Scene/Compose/TableViewCell/ComposeStatusAttachmentTableViewCell.swift +++ b/Mastodon/Scene/Compose/TableViewCell/ComposeStatusAttachmentTableViewCell.swift @@ -30,7 +30,7 @@ final class ComposeStatusAttachmentTableViewCell: UITableViewCell { let collectionViewLayout = ComposeStatusAttachmentTableViewCell.createLayout() let collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) collectionView.register(ComposeStatusAttachmentCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ComposeStatusAttachmentCollectionViewCell.self)) - collectionView.backgroundColor = Asset.Scene.Compose.background.color + collectionView.backgroundColor = .clear collectionView.alwaysBounceVertical = true collectionView.isScrollEnabled = false return collectionView @@ -51,6 +51,9 @@ final class ComposeStatusAttachmentTableViewCell: UITableViewCell { extension ComposeStatusAttachmentTableViewCell { private func _init() { + backgroundColor = .clear + contentView.backgroundColor = .clear + collectionView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(collectionView) collectionViewHeightLayoutConstraint = collectionView.heightAnchor.constraint(equalToConstant: 200).priority(.defaultHigh) diff --git a/Mastodon/Scene/Compose/TableViewCell/ComposeStatusPollTableViewCell.swift b/Mastodon/Scene/Compose/TableViewCell/ComposeStatusPollTableViewCell.swift index c12c346f3..f1a1693a2 100644 --- a/Mastodon/Scene/Compose/TableViewCell/ComposeStatusPollTableViewCell.swift +++ b/Mastodon/Scene/Compose/TableViewCell/ComposeStatusPollTableViewCell.swift @@ -40,7 +40,7 @@ final class ComposeStatusPollTableViewCell: UITableViewCell { collectionView.register(ComposeStatusPollOptionCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ComposeStatusPollOptionCollectionViewCell.self)) collectionView.register(ComposeStatusPollOptionAppendEntryCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ComposeStatusPollOptionAppendEntryCollectionViewCell.self)) collectionView.register(ComposeStatusPollExpiresOptionCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ComposeStatusPollExpiresOptionCollectionViewCell.self)) - collectionView.backgroundColor = Asset.Scene.Compose.background.color + collectionView.backgroundColor = .clear collectionView.alwaysBounceVertical = true collectionView.isScrollEnabled = false return collectionView @@ -61,6 +61,9 @@ final class ComposeStatusPollTableViewCell: UITableViewCell { extension ComposeStatusPollTableViewCell { private func _init() { + backgroundColor = .clear + contentView.backgroundColor = .clear + collectionView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(collectionView) collectionViewHeightLayoutConstraint = collectionView.heightAnchor.constraint(equalToConstant: 300).priority(.defaultHigh) diff --git a/Mastodon/Scene/Compose/View/AttachmentContainerView+EmptyStateView.swift b/Mastodon/Scene/Compose/View/AttachmentContainerView+EmptyStateView.swift index ca45e33d5..b9e92f515 100644 --- a/Mastodon/Scene/Compose/View/AttachmentContainerView+EmptyStateView.swift +++ b/Mastodon/Scene/Compose/View/AttachmentContainerView+EmptyStateView.swift @@ -52,7 +52,7 @@ extension AttachmentContainerView.EmptyStateView { layer.masksToBounds = true layer.cornerRadius = AttachmentContainerView.containerViewCornerRadius layer.cornerCurve = .continuous - backgroundColor = Asset.Colors.Background.systemGroupedBackground.color + backgroundColor = ThemeService.shared.currentTheme.value.systemGroupedBackgroundColor let stackView = UIStackView() stackView.axis = .vertical diff --git a/Mastodon/Scene/Compose/View/AttachmentContainerView.swift b/Mastodon/Scene/Compose/View/AttachmentContainerView.swift index 71893c474..faa085593 100644 --- a/Mastodon/Scene/Compose/View/AttachmentContainerView.swift +++ b/Mastodon/Scene/Compose/View/AttachmentContainerView.swift @@ -14,7 +14,11 @@ final class AttachmentContainerView: UIView { var descriptionBackgroundViewFrameObservation: NSKeyValueObservation? - let activityIndicatorView = UIActivityIndicatorView(style: .large) + let activityIndicatorView: UIActivityIndicatorView = { + let activityIndicatorView = UIActivityIndicatorView(style: .large) + activityIndicatorView.color = UIColor.white.withAlphaComponent(0.8) + return activityIndicatorView + }() let previewImageView: UIImageView = { let imageView = UIImageView() @@ -119,15 +123,32 @@ extension AttachmentContainerView { activityIndicatorView.centerYAnchor.constraint(equalTo: previewImageView.centerYAnchor), ]) + setupBroader() + emptyStateView.isHidden = true activityIndicatorView.hidesWhenStopped = true activityIndicatorView.startAnimating() descriptionTextView.delegate = self } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + setupBroader() + } } +extension AttachmentContainerView { + + private func setupBroader() { + emptyStateView.layer.borderWidth = 1 + emptyStateView.layer.borderColor = traitCollection.userInterfaceStyle == .dark ? ThemeService.shared.currentTheme.value.tableViewCellSelectionBackgroundColor.cgColor : nil + } + +} + // MARK: - UITextViewDelegate extension AttachmentContainerView: UITextViewDelegate { func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { diff --git a/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewController.swift b/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewController.swift index ee5c44971..858a7b0f2 100644 --- a/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewController.swift +++ b/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewController.swift @@ -59,7 +59,13 @@ extension HashtagTimelineViewController { titleView.update(title: viewModel.hashtag, subtitle: nil, emojiDict: [:]) navigationItem.titleView = titleView - view.backgroundColor = Asset.Colors.Background.secondarySystemBackground.color + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.secondarySystemBackgroundColor + } + .store(in: &disposeBag) navigationItem.rightBarButtonItem = composeBarButtonItem diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift index 8f1558554..333a42ae0 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift @@ -79,9 +79,16 @@ extension HomeTimelineViewController { override func viewDidLoad() { super.viewDidLoad() - + + title = L10n.Scene.HomeTimeline.title - view.backgroundColor = Asset.Colors.Background.secondarySystemBackground.color + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.secondarySystemBackgroundColor + } + .store(in: &disposeBag) navigationItem.leftBarButtonItem = settingBarButtonItem navigationItem.titleView = titleView titleView.delegate = self diff --git a/Mastodon/Scene/MainTab/MainTabBarController.swift b/Mastodon/Scene/MainTab/MainTabBarController.swift index 3ef16785a..397589fd5 100644 --- a/Mastodon/Scene/MainTab/MainTabBarController.swift +++ b/Mastodon/Scene/MainTab/MainTabBarController.swift @@ -100,8 +100,16 @@ extension MainTabBarController { delegate = self - view.backgroundColor = Asset.Colors.Background.systemBackground.color - + view.backgroundColor = ThemeService.shared.currentTheme.value.systemBackgroundColor +// ThemeService.shared.currentTheme +// .receive(on: RunLoop.main) +// .sink { [weak self] theme in +// guard let self = self else { return } +// // fix tab bar not update color issue +// self.tabBar.backgroundColor = theme.tabBarBackgroundColor +// } +// .store(in: &disposeBag) + let tabs = Tab.allCases let viewControllers: [UIViewController] = tabs.map { tab in let viewController = tab.viewController(context: context, coordinator: coordinator) diff --git a/Mastodon/Scene/Notification/NotificationViewController.swift b/Mastodon/Scene/Notification/NotificationViewController.swift index f2de1d803..144d06b8a 100644 --- a/Mastodon/Scene/Notification/NotificationViewController.swift +++ b/Mastodon/Scene/Notification/NotificationViewController.swift @@ -48,7 +48,13 @@ extension NotificationViewController { override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = Asset.Colors.Background.secondarySystemBackground.color + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.secondarySystemBackgroundColor + } + .store(in: &disposeBag) segmentControl.translatesAutoresizingMaskIntoConstraints = false navigationItem.titleView = segmentControl NSLayoutConstraint.activate([ diff --git a/Mastodon/Scene/Notification/TableViewCell/NotificationStatusTableViewCell.swift b/Mastodon/Scene/Notification/TableViewCell/NotificationStatusTableViewCell.swift index a015fb5c5..14a0ea5e0 100644 --- a/Mastodon/Scene/Notification/TableViewCell/NotificationStatusTableViewCell.swift +++ b/Mastodon/Scene/Notification/TableViewCell/NotificationStatusTableViewCell.swift @@ -137,13 +137,6 @@ final class NotificationStatusTableViewCell: UITableViewCell, StatusCell { extension NotificationStatusTableViewCell { func configure() { - backgroundColor = Asset.Colors.Background.systemBackground.color - selectedBackgroundView = { - let view = UIView() - view.backgroundColor = Asset.Colors.Background.Cell.highlight.color - return view - }() - containerStackView.axis = .horizontal containerStackView.alignment = .top containerStackView.distribution = .fill @@ -225,14 +218,16 @@ extension NotificationStatusTableViewCell { statusView.trailingAnchor.constraint(equalTo: statusContainerView.layoutMarginsGuide.trailingAnchor), statusView.bottomAnchor.constraint(equalTo: statusContainerView.layoutMarginsGuide.bottomAnchor), ]) - statusContainerView.backgroundColor = UIColor(dynamicProvider: { collection in - switch collection.userInterfaceStyle { - case .dark: - return Asset.Colors.Background.tertiarySystemGroupedBackground.color - default: - return .clear + + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.statusContainerView.backgroundColor = UIColor(dynamicProvider: { traitCollection in + return traitCollection.userInterfaceStyle == .light ? theme.systemBackgroundColor : theme.tertiarySystemGroupedBackgroundColor + }) } - }) + .store(in: &disposeBag) // remove item don't display statusView.actionToolbarContainer.removeFromStackView() // it affect stackView's height, need remove diff --git a/Mastodon/Scene/Profile/Favorite/FavoriteViewController.swift b/Mastodon/Scene/Profile/Favorite/FavoriteViewController.swift index d34240a85..3af4f884a 100644 --- a/Mastodon/Scene/Profile/Favorite/FavoriteViewController.swift +++ b/Mastodon/Scene/Profile/Favorite/FavoriteViewController.swift @@ -47,7 +47,15 @@ extension FavoriteViewController { override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = Asset.Colors.Background.secondarySystemBackground.color + view.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.secondarySystemBackgroundColor + } + .store(in: &disposeBag) + navigationItem.titleView = titleView titleView.update(title: L10n.Scene.Favorite.title, subtitle: nil, emojiDict: [:]) diff --git a/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift b/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift index 94be3e6f5..bf109888d 100644 --- a/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift +++ b/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift @@ -87,8 +87,14 @@ extension ProfileHeaderViewController { override func viewDidLoad() { super.viewDidLoad() - - view.backgroundColor = Asset.Colors.Background.systemGroupedBackground.color + + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.systemGroupedBackgroundColor + } + .store(in: &disposeBag) profileHeaderView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(profileHeaderView) @@ -105,6 +111,7 @@ extension ProfileHeaderViewController { profileFieldCollectionViewCellDelegate: self, profileFieldAddEntryCollectionViewCellDelegate: self ) + let longPressReorderGesture = UILongPressGestureRecognizer(target: self, action: #selector(ProfileHeaderViewController.longPressReorderGestureHandler(_:))) profileHeaderView.fieldCollectionView.addGestureRecognizer(longPressReorderGesture) diff --git a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift index ad9c3dbc4..2ba4cef86 100644 --- a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift +++ b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift @@ -7,6 +7,7 @@ import os.log import UIKit +import Combine import ActiveLabel import TwitterTextEditor import FLAnimatedImage @@ -36,6 +37,7 @@ final class ProfileHeaderView: UIView { static let bannerImageViewOverlayViewBackgroundEditingColor = UIColor.black.withAlphaComponent(0.8) weak var delegate: ProfileHeaderViewDelegate? + var disposeBag = Set() var state: State? @@ -213,7 +215,6 @@ final class ProfileHeaderView: UIView { collectionView.register(ProfileFieldAddEntryCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ProfileFieldAddEntryCollectionViewCell.self)) collectionView.register(ProfileFieldCollectionViewHeaderFooterView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: ProfileFieldCollectionViewHeaderFooterView.headerReuseIdentifer) collectionView.register(ProfileFieldCollectionViewHeaderFooterView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: ProfileFieldCollectionViewHeaderFooterView.footerReuseIdentifer) - collectionView.backgroundColor = Asset.Colors.Background.secondaryGroupedSystemBackground.color collectionView.isScrollEnabled = false return collectionView }() @@ -238,7 +239,14 @@ final class ProfileHeaderView: UIView { extension ProfileHeaderView { private func _init() { - backgroundColor = Asset.Colors.Background.systemGroupedBackground.color + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.backgroundColor = theme.systemGroupedBackgroundColor + self.fieldCollectionView.backgroundColor = theme.profileFieldCollectionViewBackgroundColor + } + .store(in: &disposeBag) // banner bannerContainerView.translatesAutoresizingMaskIntoConstraints = false diff --git a/Mastodon/Scene/Profile/ProfileViewController.swift b/Mastodon/Scene/Profile/ProfileViewController.swift index 7b6a1db86..e5104c4cb 100644 --- a/Mastodon/Scene/Profile/ProfileViewController.swift +++ b/Mastodon/Scene/Profile/ProfileViewController.swift @@ -142,7 +142,13 @@ extension ProfileViewController { override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = Asset.Colors.Background.systemGroupedBackground.color + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.secondarySystemBackgroundColor + } + .store(in: &disposeBag) let barAppearance = UINavigationBarAppearance() barAppearance.configureWithTransparentBackground() diff --git a/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift b/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift index 10b82fd17..f3803da01 100644 --- a/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift +++ b/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift @@ -47,7 +47,14 @@ extension UserTimelineViewController { override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = Asset.Colors.Background.secondarySystemBackground.color + view.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.secondarySystemBackgroundColor + } + .store(in: &disposeBag) tableView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(tableView) diff --git a/Mastodon/Scene/PublicTimeline/PublicTimelineViewController.swift b/Mastodon/Scene/PublicTimeline/PublicTimelineViewController.swift index 781d2ce1b..29d84b791 100644 --- a/Mastodon/Scene/PublicTimeline/PublicTimelineViewController.swift +++ b/Mastodon/Scene/PublicTimeline/PublicTimelineViewController.swift @@ -45,8 +45,7 @@ extension PublicTimelineViewController { super.viewDidLoad() title = "Public" - view.backgroundColor = Asset.Colors.Background.systemGroupedBackground.color - + view.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor tableView.refreshControl = refreshControl refreshControl.addTarget(self, action: #selector(PublicTimelineViewController.refreshControlValueChanged(_:)), for: .valueChanged) // bind refresh control diff --git a/Mastodon/Scene/Report/ReportFooterView.swift b/Mastodon/Scene/Report/ReportFooterView.swift index a64a556d3..0bad78cb2 100644 --- a/Mastodon/Scene/Report/ReportFooterView.swift +++ b/Mastodon/Scene/Report/ReportFooterView.swift @@ -53,8 +53,8 @@ final class ReportFooterView: UIView { override init(frame: CGRect) { super.init(frame: frame) - self.backgroundColor = Asset.Colors.Background.systemElevatedBackground.color - + self.backgroundColor = ThemeService.shared.currentTheme.value.systemElevatedBackgroundColor + stackview.addArrangedSubview(nextStepButton) stackview.addArrangedSubview(skipButton) addSubview(stackview) diff --git a/Mastodon/Scene/Report/ReportHeaderView.swift b/Mastodon/Scene/Report/ReportHeaderView.swift index a3d821095..23572c118 100644 --- a/Mastodon/Scene/Report/ReportHeaderView.swift +++ b/Mastodon/Scene/Report/ReportHeaderView.swift @@ -65,7 +65,7 @@ final class ReportHeaderView: UIView { override init(frame: CGRect) { super.init(frame: frame) - self.backgroundColor = Asset.Colors.Background.systemElevatedBackground.color + self.backgroundColor = ThemeService.shared.currentTheme.value.systemElevatedBackgroundColor stackview.addArrangedSubview(titleLabel) stackview.addArrangedSubview(contentLabel) addSubview(stackview) diff --git a/Mastodon/Scene/Report/ReportViewController.swift b/Mastodon/Scene/Report/ReportViewController.swift index 7143912d5..ebe1788f8 100644 --- a/Mastodon/Scene/Report/ReportViewController.swift +++ b/Mastodon/Scene/Report/ReportViewController.swift @@ -47,7 +47,7 @@ class ReportViewController: UIViewController, NeedsDependency { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false view.setContentHuggingPriority(.defaultLow, for: .vertical) - view.backgroundColor = Asset.Colors.Background.systemElevatedBackground.color + view.backgroundColor = ThemeService.shared.currentTheme.value.systemElevatedBackgroundColor return view }() @@ -109,7 +109,15 @@ class ReportViewController: UIViewController, NeedsDependency { // MAKR: - Private methods private func setupView() { - view.backgroundColor = Asset.Colors.Background.secondarySystemBackground.color + view.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.secondarySystemBackgroundColor + } + .store(in: &disposeBag) + setupNavigation() stackview.addArrangedSubview(header) diff --git a/Mastodon/Scene/Report/ReportedStatusTableviewCell.swift b/Mastodon/Scene/Report/ReportedStatusTableviewCell.swift index 80046b13d..0db0e79ab 100644 --- a/Mastodon/Scene/Report/ReportedStatusTableviewCell.swift +++ b/Mastodon/Scene/Report/ReportedStatusTableviewCell.swift @@ -89,7 +89,14 @@ final class ReportedStatusTableViewCell: UITableViewCell, StatusCell { extension ReportedStatusTableViewCell { private func _init() { - backgroundColor = Asset.Colors.Background.secondaryGroupedSystemBackground.color + backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemGroupedBackgroundColor + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemGroupedBackgroundColor + } + .store(in: &disposeBag) checkbox.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(checkbox) diff --git a/Mastodon/Scene/Search/SearchViewController.swift b/Mastodon/Scene/Search/SearchViewController.swift index bc04c0b69..06b5eeced 100644 --- a/Mastodon/Scene/Search/SearchViewController.swift +++ b/Mastodon/Scene/Search/SearchViewController.swift @@ -39,20 +39,17 @@ final class SearchViewController: UIViewController, NeedsDependency { let statusBar: UIView = { let view = UIView() - view.backgroundColor = Asset.Colors.Background.bar.color return view }() let searchBar: UISearchBar = { let searchBar = UISearchBar() searchBar.placeholder = L10n.Scene.Search.Searchbar.placeholder - searchBar.tintColor = Asset.Colors.brandBlue.color searchBar.translatesAutoresizingMaskIntoConstraints = false // let micImage = UIImage(systemName: "mic.fill") // searchBar.setImage(micImage, for: .bookmark, state: .normal) // searchBar.showsBookmarkButton = true searchBar.scopeButtonTitles = [L10n.Scene.Search.Searching.Segment.all, L10n.Scene.Search.Searching.Segment.people, L10n.Scene.Search.Searching.Segment.hashtags] - searchBar.barTintColor = Asset.Colors.Background.bar.color return searchBar }() @@ -99,7 +96,6 @@ final class SearchViewController: UIViewController, NeedsDependency { // searching let searchingTableView: UITableView = { let tableView = UITableView() - tableView.backgroundColor = Asset.Colors.Background.systemBackground.color tableView.rowHeight = UITableView.automaticDimension tableView.separatorStyle = .singleLine tableView.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) @@ -109,7 +105,6 @@ final class SearchViewController: UIViewController, NeedsDependency { lazy var searchHeader: UIView = { let view = UIView() - view.backgroundColor = Asset.Colors.Background.systemGroupedBackground.color view.frame = CGRect(origin: .zero, size: CGSize(width: searchingTableView.frame.width, height: 56)) return view }() @@ -133,12 +128,24 @@ final class SearchViewController: UIViewController, NeedsDependency { extension SearchViewController { override func viewDidLoad() { super.viewDidLoad() + let barAppearance = UINavigationBarAppearance() barAppearance.configureWithTransparentBackground() navigationItem.standardAppearance = barAppearance navigationItem.compactAppearance = barAppearance navigationItem.scrollEdgeAppearance = barAppearance - view.backgroundColor = Asset.Colors.Background.systemGroupedBackground.color + + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.systemGroupedBackgroundColor + self.searchHeader.backgroundColor = theme.systemGroupedBackgroundColor + self.searchingTableView.backgroundColor = theme.systemBackgroundColor + self.statusBar.backgroundColor = theme.navigationBarBackgroundColor + } + .store(in: &disposeBag) + navigationItem.hidesBackButton = true setupSearchBar() @@ -152,6 +159,12 @@ extension SearchViewController { view.bringSubviewToFront(statusBar) } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + searchBar.tintColor = Asset.Colors.brandBlue.color + } + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) diff --git a/Mastodon/Scene/Search/TableViewCell/SearchingTableViewCell.swift b/Mastodon/Scene/Search/TableViewCell/SearchingTableViewCell.swift index d0e06ba18..6759eecba 100644 --- a/Mastodon/Scene/Search/TableViewCell/SearchingTableViewCell.swift +++ b/Mastodon/Scene/Search/TableViewCell/SearchingTableViewCell.swift @@ -54,8 +54,6 @@ final class SearchingTableViewCell: UITableViewCell { extension SearchingTableViewCell { private func configure() { - backgroundColor = Asset.Colors.Background.systemBackground.color - let containerStackView = UIStackView() containerStackView.axis = .horizontal containerStackView.distribution = .fill diff --git a/Mastodon/Scene/Settings/SettingsViewController.swift b/Mastodon/Scene/Settings/SettingsViewController.swift index c494ca021..8c74bbcfa 100644 --- a/Mastodon/Scene/Settings/SettingsViewController.swift +++ b/Mastodon/Scene/Settings/SettingsViewController.swift @@ -95,7 +95,7 @@ class SettingsViewController: UIViewController, NeedsDependency { tableView.delegate = self tableView.rowHeight = UITableView.automaticDimension tableView.backgroundColor = .clear - tableView.separatorColor = Asset.Colors.Background.Cell.separator.color + tableView.separatorColor = ThemeService.shared.currentTheme.value.separator tableView.register(SettingsAppearanceTableViewCell.self, forCellReuseIdentifier: String(describing: SettingsAppearanceTableViewCell.self)) tableView.register(SettingsToggleTableViewCell.self, forCellReuseIdentifier: String(describing: SettingsToggleTableViewCell.self)) @@ -129,6 +129,13 @@ class SettingsViewController: UIViewController, NeedsDependency { viewModel.viewDidLoad.send() } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + // make large title not collapsed + navigationController?.navigationBar.sizeToFit() + } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() @@ -186,16 +193,31 @@ class SettingsViewController: UIViewController, NeedsDependency { } private func setupView() { - view.backgroundColor = UIColor(dynamicProvider: { traitCollection in + self.view.backgroundColor = UIColor(dynamicProvider: { traitCollection in switch traitCollection.userInterfaceLevel { case .elevated where traitCollection.userInterfaceStyle == .dark: - return Asset.Colors.Background.systemElevatedBackground.color + return ThemeService.shared.currentTheme.value.systemElevatedBackgroundColor default: - return Asset.Colors.Background.secondarySystemBackground.color + return ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor } }) + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = UIColor(dynamicProvider: { traitCollection in + switch traitCollection.userInterfaceLevel { + case .elevated where traitCollection.userInterfaceStyle == .dark: + return theme.systemElevatedBackgroundColor + default: + return theme.secondarySystemBackgroundColor + } + }) + + } + .store(in: &disposeBag) + setupNavigation() - view.addSubview(tableView) NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: view.topAnchor), @@ -215,12 +237,6 @@ class SettingsViewController: UIViewController, NeedsDependency { target: self, action: #selector(doneButtonDidClick)) navigationItem.title = L10n.Scene.Settings.title - - let barAppearance = UINavigationBarAppearance() - barAppearance.configureWithDefaultBackground() - navigationItem.standardAppearance = barAppearance - navigationItem.compactAppearance = barAppearance - navigationItem.scrollEdgeAppearance = barAppearance } private func setupTableView() { @@ -332,6 +348,9 @@ extension SettingsViewController: UITableViewDelegate { case .appearance: // do nothing break + case .appearanceDarkMode: + // do nothing + break case .notification: // do nothing break @@ -418,6 +437,23 @@ extension SettingsViewController: SettingsToggleCellDelegate { guard let indexPath = tableView.indexPath(for: cell) else { return } let item = dataSource.itemIdentifier(for: indexPath) switch item { + case .appearanceDarkMode(let settingObjectID): + let isOn = `switch`.isOn + let managedObjectContext = context.backgroundManagedObjectContext + managedObjectContext.performChanges { + let setting = managedObjectContext.object(with: settingObjectID) as! Setting + setting.update(preferredTrueBlackDarkMode: isOn) + } + .sink { result in + switch result { + case .success: + ThemeService.shared.set(themeName: isOn ? .system : .mastodon) + case .failure(let error): + assertionFailure(error.localizedDescription) + break + } + } + .store(in: &disposeBag) case .notification(let settingObjectID, let switchMode): let isOn = `switch`.isOn let managedObjectContext = context.backgroundManagedObjectContext diff --git a/Mastodon/Scene/Settings/SettingsViewModel.swift b/Mastodon/Scene/Settings/SettingsViewModel.swift index 326dc0a4a..15aaf66ff 100644 --- a/Mastodon/Scene/Settings/SettingsViewModel.swift +++ b/Mastodon/Scene/Settings/SettingsViewModel.swift @@ -74,6 +74,10 @@ extension SettingsViewModel { let appearanceItems = [SettingsItem.appearance(settingObjectID: setting.objectID)] snapshot.appendSections([.appearance]) snapshot.appendItems(appearanceItems, toSection: .appearance) + + let appearanceSettingItems = [SettingsItem.appearanceDarkMode(settingObjectID: setting.objectID)] + snapshot.appendSections([.appearanceSettings]) + snapshot.appendItems(appearanceSettingItems, toSection: .appearanceSettings) let notificationItems = SettingsItem.NotificationSwitchMode.allCases.map { mode in SettingsItem.notification(settingObjectID: setting.objectID, switchMode: mode) @@ -129,6 +133,7 @@ extension SettingsViewModel { let setting = self.context.managedObjectContext.object(with: objectID) as! Setting cell.update(with: setting.appearance) ManagedObjectObserver.observe(object: setting) + .receive(on: DispatchQueue.main) .sink(receiveCompletion: { _ in // do nothing }, receiveValue: { [weak cell] change in @@ -141,6 +146,26 @@ extension SettingsViewModel { } cell.delegate = settingsAppearanceTableViewCellDelegate return cell + case .appearanceDarkMode(let objectID): + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsToggleTableViewCell.self), for: indexPath) as! SettingsToggleTableViewCell + cell.delegate = settingsToggleCellDelegate + cell.textLabel?.text = L10n.Scene.Settings.Section.AppearanceSettings.DarkMode.title + self.context.managedObjectContext.performAndWait { + let setting = self.context.managedObjectContext.object(with: objectID) as! Setting + cell.switchButton.isOn = setting.preferredTrueBlackDarkMode + ManagedObjectObserver.observe(object: setting) + .receive(on: DispatchQueue.main) + .sink(receiveCompletion: { _ in + // do nothing + }, receiveValue: { [weak cell] change in + guard let cell = cell else { return } + guard case .update(let object) = change.changeType, + let setting = object as? Setting else { return } + cell.switchButton.isOn = setting.preferredTrueBlackDarkMode + }) + .store(in: &cell.disposeBag) + } + return cell case .notification(let objectID, let switchMode): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsToggleTableViewCell.self), for: indexPath) as! SettingsToggleTableViewCell self.context.managedObjectContext.performAndWait { diff --git a/Mastodon/Scene/Settings/View/Cell/SettingsLinkTableViewCell.swift b/Mastodon/Scene/Settings/View/Cell/SettingsLinkTableViewCell.swift index 90350f54d..7fdbf7f02 100644 --- a/Mastodon/Scene/Settings/View/Cell/SettingsLinkTableViewCell.swift +++ b/Mastodon/Scene/Settings/View/Cell/SettingsLinkTableViewCell.swift @@ -31,6 +31,5 @@ extension SettingsLinkTableViewCell { func update(with link: SettingsItem.Link) { textLabel?.text = link.title textLabel?.textColor = link.textColor - backgroundColor = Asset.Colors.Background.secondaryGroupedSystemBackground.color } } diff --git a/Mastodon/Scene/Settings/View/Cell/SettingsToggleTableViewCell.swift b/Mastodon/Scene/Settings/View/Cell/SettingsToggleTableViewCell.swift index 0059b1144..86698d840 100644 --- a/Mastodon/Scene/Settings/View/Cell/SettingsToggleTableViewCell.swift +++ b/Mastodon/Scene/Settings/View/Cell/SettingsToggleTableViewCell.swift @@ -38,7 +38,6 @@ class SettingsToggleTableViewCell: UITableViewCell { private func setupUI() { selectionStyle = .none accessoryView = switchButton - backgroundColor = Asset.Colors.Background.secondaryGroupedSystemBackground.color switchButton.addTarget(self, action: #selector(switchValueDidChange(sender:)), for: .valueChanged) } diff --git a/Mastodon/Scene/Share/View/Content/ContentWarningOverlayView.swift b/Mastodon/Scene/Share/View/Content/ContentWarningOverlayView.swift index 0b3741744..931932060 100644 --- a/Mastodon/Scene/Share/View/Content/ContentWarningOverlayView.swift +++ b/Mastodon/Scene/Share/View/Content/ContentWarningOverlayView.swift @@ -7,6 +7,7 @@ import os.log import Foundation +import Combine import UIKit protocol ContentWarningOverlayViewDelegate: AnyObject { @@ -14,6 +15,8 @@ protocol ContentWarningOverlayViewDelegate: AnyObject { } class ContentWarningOverlayView: UIView { + + var disposeBag = Set() static let cornerRadius: CGFloat = 4 static let blurVisualEffect = UIBlurEffect(style: .systemUltraThinMaterial) @@ -33,7 +36,7 @@ class ContentWarningOverlayView: UIView { // for status style overlay let contentOverlayView: UIView = { let view = UIView() - view.backgroundColor = Asset.Colors.ContentWarningOverlay.background.color + view.backgroundColor = ThemeService.shared.currentTheme.value.contentWarningOverlayBackgroundColor view.applyCornerRadius(radius: ContentWarningOverlayView.cornerRadius) return view }() diff --git a/Mastodon/Scene/Share/View/Content/PollOptionView.swift b/Mastodon/Scene/Share/View/Content/PollOptionView.swift index e95de4624..6dcbcd617 100644 --- a/Mastodon/Scene/Share/View/Content/PollOptionView.swift +++ b/Mastodon/Scene/Share/View/Content/PollOptionView.swift @@ -17,6 +17,8 @@ final class PollOptionView: UIView { static let checkmarkBackgroundLeadingMargin: CGFloat = 9 private var viewStateDisposeBag = Set() + + var disposeBag = Set() let roundedBackgroundView = UIView() let voteProgressStripView: StripProgressView = { @@ -82,7 +84,7 @@ final class PollOptionView: UIView { extension PollOptionView { private func _init() { // default color in the timeline - roundedBackgroundView.backgroundColor = Asset.Colors.Background.secondarySystemBackground.color + roundedBackgroundView.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor roundedBackgroundView.translatesAutoresizingMaskIntoConstraints = false addSubview(roundedBackgroundView) diff --git a/Mastodon/Scene/Share/View/TableviewCell/PollOptionTableViewCell.swift b/Mastodon/Scene/Share/View/TableviewCell/PollOptionTableViewCell.swift index 957765e10..fdcaa95f3 100644 --- a/Mastodon/Scene/Share/View/TableviewCell/PollOptionTableViewCell.swift +++ b/Mastodon/Scene/Share/View/TableviewCell/PollOptionTableViewCell.swift @@ -9,6 +9,8 @@ import UIKit import Combine final class PollOptionTableViewCell: UITableViewCell { + + var disposeBag = Set() let pollOptionView = PollOptionView() var attribute: PollItem.Attribute? @@ -29,7 +31,7 @@ final class PollOptionTableViewCell: UITableViewCell { guard let voteState = attribute?.voteState else { return } switch voteState { case .hidden: - let color = Asset.Colors.Background.systemGroupedBackground.color + let color = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor pollOptionView.roundedBackgroundView.backgroundColor = isHighlighted ? color.withAlphaComponent(0.8) : color case .reveal: break @@ -42,7 +44,7 @@ final class PollOptionTableViewCell: UITableViewCell { guard let voteState = attribute?.voteState else { return } switch voteState { case .hidden: - let color = Asset.Colors.Background.systemGroupedBackground.color + let color = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor pollOptionView.roundedBackgroundView.backgroundColor = isHighlighted ? color.withAlphaComponent(0.8) : color case .reveal: break diff --git a/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift b/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift index 8656a2b64..27461cfc6 100644 --- a/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift +++ b/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift @@ -103,13 +103,6 @@ final class StatusTableViewCell: UITableViewCell, StatusCell { extension StatusTableViewCell { private func _init() { - backgroundColor = Asset.Colors.Background.systemBackground.color - selectedBackgroundView = { - let view = UIView() - view.backgroundColor = Asset.Colors.Background.Cell.highlight.color - return view - }() - statusView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(statusView) NSLayoutConstraint.activate([ @@ -214,7 +207,7 @@ extension StatusTableViewCell: UITableViewDelegate { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: indexPath: %s. PollID: %s", ((#file as NSString).lastPathComponent), #line, #function, indexPath.debugDescription, pollID ?? "") } guard let item = diffableDataSource.itemIdentifier(for: indexPath), - case let .opion(objectID, _) = item, + case let .option(objectID, _) = item, let option = delegate?.managedObjectContext.object(with: objectID) as? PollOption else { return false } @@ -236,7 +229,7 @@ extension StatusTableViewCell: UITableViewDelegate { guard let context = delegate?.context else { return nil } guard let activeMastodonAuthenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { return nil } guard let item = diffableDataSource.itemIdentifier(for: indexPath), - case let .opion(objectID, _) = item, + case let .option(objectID, _) = item, let option = delegate?.managedObjectContext.object(with: objectID) as? PollOption else { return nil } diff --git a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift index 80cd73cc1..3d66aed33 100644 --- a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift +++ b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift @@ -66,7 +66,16 @@ class SuggestionAccountViewController: UIViewController, NeedsDependency { extension SuggestionAccountViewController { override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = Asset.Colors.Background.systemBackground.color + + view.backgroundColor = ThemeService.shared.currentTheme.value.systemBackgroundColor + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.systemBackgroundColor + } + .store(in: &disposeBag) + title = L10n.Scene.SuggestionAccount.title navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.done, diff --git a/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift b/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift index 221f9a208..30f7688a6 100644 --- a/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift +++ b/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift @@ -87,8 +87,6 @@ final class SuggestionAccountTableViewCell: UITableViewCell { extension SuggestionAccountTableViewCell { private func configure() { - backgroundColor = .clear - let containerStackView = UIStackView() containerStackView.axis = .horizontal containerStackView.distribution = .fill diff --git a/Mastodon/Scene/Thread/ThreadViewController.swift b/Mastodon/Scene/Thread/ThreadViewController.swift index 02cf3c38d..99c448801 100644 --- a/Mastodon/Scene/Thread/ThreadViewController.swift +++ b/Mastodon/Scene/Thread/ThreadViewController.swift @@ -52,7 +52,13 @@ extension ThreadViewController { override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = Asset.Colors.Background.secondarySystemBackground.color + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.view.backgroundColor = theme.secondarySystemBackgroundColor + } + .store(in: &disposeBag) navigationItem.title = L10n.Scene.Thread.backTitle navigationItem.titleView = titleView navigationItem.rightBarButtonItem = replyBarButtonItem diff --git a/Mastodon/Service/ThemeService/MastodonTheme.swift b/Mastodon/Service/ThemeService/MastodonTheme.swift new file mode 100644 index 000000000..6476d5a74 --- /dev/null +++ b/Mastodon/Service/ThemeService/MastodonTheme.swift @@ -0,0 +1,36 @@ +// +// MastodonTheme.swift +// Mastodon +// +// Created by MainasuK Cirno on 2021-7-5. +// + +import UIKit + +struct MastodonTheme: Theme { + let systemBackgroundColor = Asset.Theme.Mastodon.systemBackground.color + let secondarySystemBackgroundColor = Asset.Theme.Mastodon.secondarySystemBackground.color + let tertiarySystemBackgroundColor = Asset.Theme.Mastodon.tertiarySystemBackground.color + + let systemElevatedBackgroundColor = Asset.Theme.Mastodon.systemElevatedBackground.color + + let systemGroupedBackgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color + let secondarySystemGroupedBackgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color + let tertiarySystemGroupedBackgroundColor = Asset.Theme.Mastodon.tertiarySystemGroupedBackground.color + + let navigationBarBackgroundColor = Asset.Theme.Mastodon.navigationBarBackground.color + + let tabBarBackgroundColor = Asset.Theme.Mastodon.tabBarBackground.color + let tabBarItemSelectedIconColor = Asset.Colors.brandBlue.color + let tabBarItemFocusedIconColor = Asset.Theme.Mastodon.tabBarItemInactiveIconColor.color + let tabBarItemNormalIconColor = Asset.Theme.Mastodon.tabBarItemInactiveIconColor.color + let tabBarItemDisabledIconColor = Asset.Theme.Mastodon.tabBarItemInactiveIconColor.color + + let separator = Asset.Theme.Mastodon.separator.color + + let tableViewCellBackgroundColor = Asset.Theme.Mastodon.tableViewCellBackground.color + let tableViewCellSelectionBackgroundColor = Asset.Theme.Mastodon.tableViewCellSelectionBackground.color + + let contentWarningOverlayBackgroundColor = Asset.Theme.Mastodon.contentWarningOverlayBackground.color + let profileFieldCollectionViewBackgroundColor = Asset.Theme.Mastodon.profileFieldCollectionViewBackground.color +} diff --git a/Mastodon/Service/ThemeService/SystemTheme.swift b/Mastodon/Service/ThemeService/SystemTheme.swift new file mode 100644 index 000000000..4a7a1f963 --- /dev/null +++ b/Mastodon/Service/ThemeService/SystemTheme.swift @@ -0,0 +1,36 @@ +// +// SystemTheme.swift +// Mastodon +// +// Created by MainasuK Cirno on 2021-7-5. +// + +import UIKit + +struct SystemTheme: Theme { + let systemBackgroundColor = Asset.Theme.System.systemBackground.color + let secondarySystemBackgroundColor = Asset.Theme.System.secondarySystemBackground.color + let tertiarySystemBackgroundColor = Asset.Theme.System.tertiarySystemBackground.color + + let systemElevatedBackgroundColor = Asset.Theme.System.systemElevatedBackground.color + + let systemGroupedBackgroundColor = Asset.Theme.System.systemGroupedBackground.color + let secondarySystemGroupedBackgroundColor = Asset.Theme.System.secondaryGroupedSystemBackground.color + let tertiarySystemGroupedBackgroundColor = Asset.Theme.System.tertiarySystemGroupedBackground.color + + let navigationBarBackgroundColor = Asset.Theme.System.navigationBarBackground.color + + let tabBarBackgroundColor = Asset.Theme.System.tabBarBackground.color + let tabBarItemSelectedIconColor = Asset.Colors.brandBlue.color + let tabBarItemFocusedIconColor = Asset.Theme.System.tabBarItemInactiveIconColor.color + let tabBarItemNormalIconColor = Asset.Theme.System.tabBarItemInactiveIconColor.color + let tabBarItemDisabledIconColor = Asset.Theme.System.tabBarItemInactiveIconColor.color + + let separator = Asset.Theme.System.separator.color + + let tableViewCellBackgroundColor = Asset.Theme.System.tableViewCellBackground.color + let tableViewCellSelectionBackgroundColor = Asset.Theme.System.tableViewCellSelectionBackground.color + + let contentWarningOverlayBackgroundColor = Asset.Theme.System.contentWarningOverlayBackground.color + let profileFieldCollectionViewBackgroundColor = Asset.Theme.System.profileFieldCollectionViewBackground.color +} diff --git a/Mastodon/Service/ThemeService/Theme.swift b/Mastodon/Service/ThemeService/Theme.swift new file mode 100644 index 000000000..6516945d8 --- /dev/null +++ b/Mastodon/Service/ThemeService/Theme.swift @@ -0,0 +1,51 @@ +// +// Theme.swift +// Mastodon +// +// Created by MainasuK Cirno on 2021-7-5. +// + +import UIKit + +protocol Theme { + var systemBackgroundColor: UIColor { get } + var secondarySystemBackgroundColor: UIColor { get } + var tertiarySystemBackgroundColor: UIColor { get } + + var systemElevatedBackgroundColor: UIColor { get } + + var systemGroupedBackgroundColor: UIColor { get } + var secondarySystemGroupedBackgroundColor: UIColor { get } + var tertiarySystemGroupedBackgroundColor: UIColor { get } + + var navigationBarBackgroundColor: UIColor { get } + + var tabBarBackgroundColor: UIColor { get } + var tabBarItemSelectedIconColor: UIColor { get } + var tabBarItemFocusedIconColor: UIColor { get } + var tabBarItemNormalIconColor: UIColor { get } + var tabBarItemDisabledIconColor: UIColor { get } + + var separator: UIColor { get } + + var tableViewCellBackgroundColor: UIColor { get } + var tableViewCellSelectionBackgroundColor: UIColor { get } + + var contentWarningOverlayBackgroundColor: UIColor { get } + var profileFieldCollectionViewBackgroundColor: UIColor { get } + +} + +enum ThemeName: String, CaseIterable { + case system + case mastodon +} + +extension ThemeName { + var theme: Theme { + switch self { + case .system: return SystemTheme() + case .mastodon: return MastodonTheme() + } + } +} diff --git a/Mastodon/Service/ThemeService/ThemeService.swift b/Mastodon/Service/ThemeService/ThemeService.swift new file mode 100644 index 000000000..8a1b94179 --- /dev/null +++ b/Mastodon/Service/ThemeService/ThemeService.swift @@ -0,0 +1,71 @@ +// +// ThemeService.swift +// Mastodon +// +// Created by MainasuK Cirno on 2021-7-5. +// + +import UIKit +import Combine + +// ref: https://zamzam.io/protocol-oriented-themes-for-ios-apps/ +final class ThemeService { + + // MARK: - Singleton + public static let shared = ThemeService() + + let currentTheme: CurrentValueSubject + + private init() { + let theme = ThemeName(rawValue: UserDefaults.shared.currentThemeNameRawValue)?.theme ?? ThemeName.mastodon.theme + currentTheme = CurrentValueSubject(theme) + } + + func set(themeName: ThemeName) { + UserDefaults.shared.currentThemeNameRawValue = themeName.rawValue + + let theme = themeName.theme + apply(theme: theme) + currentTheme.value = theme + } + + func apply(theme: Theme) { + // set navigation bar appearance + let appearance = UINavigationBarAppearance() + appearance.configureWithDefaultBackground() + appearance.backgroundColor = theme.navigationBarBackgroundColor + UINavigationBar.appearance().standardAppearance = appearance + UINavigationBar.appearance().compactAppearance = appearance + UINavigationBar.appearance().scrollEdgeAppearance = appearance + + // set tab bar appearance + let tabBarAppearance = UITabBarAppearance() + tabBarAppearance.configureWithDefaultBackground() + + let tabBarItemAppearance = UITabBarItemAppearance() + tabBarItemAppearance.selected.iconColor = theme.tabBarItemSelectedIconColor + tabBarItemAppearance.focused.iconColor = theme.tabBarItemFocusedIconColor + tabBarItemAppearance.normal.iconColor = theme.tabBarItemNormalIconColor + tabBarItemAppearance.disabled.iconColor = theme.tabBarItemDisabledIconColor + tabBarAppearance.stackedLayoutAppearance = tabBarItemAppearance + tabBarAppearance.inlineLayoutAppearance = tabBarItemAppearance + tabBarAppearance.compactInlineLayoutAppearance = tabBarItemAppearance + + tabBarAppearance.backgroundColor = theme.tabBarBackgroundColor + tabBarAppearance.selectionIndicatorTintColor = Asset.Colors.brandBlue.color + UITabBar.appearance().standardAppearance = tabBarAppearance + UITabBar.appearance().barTintColor = theme.tabBarBackgroundColor + + // set table view cell appearance + UITableViewCell.appearance().backgroundColor = theme.tableViewCellBackgroundColor + UITableViewCell.appearance(whenContainedInInstancesOf: [SettingsViewController.self]).backgroundColor = theme.secondarySystemGroupedBackgroundColor + UITableViewCell.appearance().selectionColor = theme.tableViewCellSelectionBackgroundColor + + // set search bar appearance + UISearchBar.appearance().barTintColor = theme.navigationBarBackgroundColor + UISearchBar.appearance().tintColor = Asset.Colors.brandBlue.color + + } + +} + diff --git a/Mastodon/Supporting Files/AppDelegate.swift b/Mastodon/Supporting Files/AppDelegate.swift index 392d2944c..3598e0192 100644 --- a/Mastodon/Supporting Files/AppDelegate.swift +++ b/Mastodon/Supporting Files/AppDelegate.swift @@ -23,6 +23,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { AppSecret.default.register() + + // configure appearance + ThemeService.shared.apply(theme: ThemeService.shared.currentTheme.value) // Update app version info. See: `Settings.bundle` UserDefaults.standard.setValue(UIApplication.appVersion(), forKey: "Mastodon.appVersion") diff --git a/Mastodon/Supporting Files/SceneDelegate.swift b/Mastodon/Supporting Files/SceneDelegate.swift index f6f6341a9..695f2df80 100644 --- a/Mastodon/Supporting Files/SceneDelegate.swift +++ b/Mastodon/Supporting Files/SceneDelegate.swift @@ -15,6 +15,7 @@ import FPSIndicator class SceneDelegate: UIResponder, UIWindowSceneDelegate { + var disposeBag = Set() var observations = Set() var window: UIWindow? @@ -34,30 +35,18 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // set tint color window.tintColor = Asset.Colors.brandBlue.color - // set navigation bar appearance - let appearance = UINavigationBarAppearance() - appearance.configureWithDefaultBackground() - appearance.backgroundColor = Asset.Colors.Background.bar.color - UINavigationBar.appearance().standardAppearance = appearance - UINavigationBar.appearance().compactAppearance = appearance - UINavigationBar.appearance().scrollEdgeAppearance = appearance - - // set tab bar appearance - let tabBarAppearance = UITabBarAppearance() - tabBarAppearance.configureWithDefaultBackground() - - let tabBarItemAppearance = UITabBarItemAppearance() - tabBarItemAppearance.selected.iconColor = Asset.Colors.brandBlue.color - tabBarItemAppearance.focused.iconColor = Asset.Colors.TabBar.itemInactive.color - tabBarItemAppearance.normal.iconColor = Asset.Colors.TabBar.itemInactive.color - tabBarItemAppearance.disabled.iconColor = Asset.Colors.TabBar.itemInactive.color - tabBarAppearance.stackedLayoutAppearance = tabBarItemAppearance - tabBarAppearance.inlineLayoutAppearance = tabBarItemAppearance - tabBarAppearance.compactInlineLayoutAppearance = tabBarItemAppearance - - tabBarAppearance.backgroundColor = Asset.Colors.Background.bar.color - tabBarAppearance.selectionIndicatorTintColor = Asset.Colors.brandBlue.color - UITabBar.appearance().standardAppearance = tabBarAppearance + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .dropFirst() + .sink { [weak self] theme in + guard let self = self else { return } + guard let window = self.window else { return } + window.subviews.forEach { view in + view.removeFromSuperview() + window.addSubview(view) + } + } + .store(in: &disposeBag) let appContext = AppContext.shared let sceneCoordinator = SceneCoordinator(scene: scene, sceneDelegate: self, appContext: appContext)