diff --git a/IceCubesApp.xcodeproj/project.pbxproj b/IceCubesApp.xcodeproj/project.pbxproj
index 793debab..15d91717 100644
--- a/IceCubesApp.xcodeproj/project.pbxproj
+++ b/IceCubesApp.xcodeproj/project.pbxproj
@@ -101,6 +101,7 @@
9FFF677C299B7B2C00FE700A /* Notifications in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF677B299B7B2C00FE700A /* Notifications */; };
9FFF6780299B7D2B00FE700A /* DesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF677F299B7D2B00FE700A /* DesignSystem */; };
9FFF6782299B7D3A00FE700A /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF6781299B7D3A00FE700A /* Account */; };
+ C8FD00C12B582F7300EB60EE /* DesignKit in Frameworks */ = {isa = PBXBuildFile; productRef = C8FD00C02B582F7300EB60EE /* DesignKit */; };
C9B22677297F6C2E001F9EFE /* ContentSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B22676297F6C2E001F9EFE /* ContentSettingsView.swift */; };
D08A9C3529956CFA00204A4A /* SwipeActionsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08A9C3429956CFA00204A4A /* SwipeActionsSettingsView.swift */; };
DA0B24FB2A6876D50045BDD7 /* SFSafeSymbols in Frameworks */ = {isa = PBXBuildFile; productRef = DA0B24FA2A6876D50045BDD7 /* SFSafeSymbols */; };
@@ -316,6 +317,7 @@
9F295540292B6C3400E0E81B /* Timeline in Frameworks */,
9F35DB4A29506FA100B3281A /* Notifications in Frameworks */,
9FC2A38B2B49D19A00DFD1C1 /* StatusKit in Frameworks */,
+ C8FD00C12B582F7300EB60EE /* DesignKit in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -650,6 +652,7 @@
DA0B24FA2A6876D50045BDD7 /* SFSafeSymbols */,
9FC2A38A2B49D19A00DFD1C1 /* StatusKit */,
9FE4CCAA2B4C848A00DA5F13 /* GiphyUISDK */,
+ C8FD00C02B582F7300EB60EE /* DesignKit */,
);
productName = IceCubesApp;
productReference = 9FBFE639292A715500C250E9 /* Ice Cubes.app */;
@@ -731,6 +734,7 @@
9F2A540829699705009B2D7C /* XCRemoteSwiftPackageReference "purchases-ios" */,
DA0B24F92A6876D40045BDD7 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */,
9FE4CCA92B4C848A00DA5F13 /* XCRemoteSwiftPackageReference "giphy-ios-sdk" */,
+ C8FD00BF2B582F7300EB60EE /* XCRemoteSwiftPackageReference "mozilla-social-ios" */,
);
productRefGroup = 9FBFE63A292A715500C250E9 /* Products */;
projectDirPath = "";
@@ -1439,6 +1443,14 @@
minimumVersion = 2.2.7;
};
};
+ C8FD00BF2B582F7300EB60EE /* XCRemoteSwiftPackageReference "mozilla-social-ios" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/MozillaSocial/mozilla-social-ios";
+ requirement = {
+ branch = ios17;
+ kind = branch;
+ };
+ };
DA0B24F92A6876D40045BDD7 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SFSafeSymbols/SFSafeSymbols";
@@ -1581,6 +1593,11 @@
isa = XCSwiftPackageProductDependency;
productName = Account;
};
+ C8FD00C02B582F7300EB60EE /* DesignKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = C8FD00BF2B582F7300EB60EE /* XCRemoteSwiftPackageReference "mozilla-social-ios" */;
+ productName = DesignKit;
+ };
DA0B24FA2A6876D50045BDD7 /* SFSafeSymbols */ = {
isa = XCSwiftPackageProductDependency;
package = DA0B24F92A6876D40045BDD7 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */;
diff --git a/IceCubesApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/IceCubesApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 234d1dfd..434a8370 100644
--- a/IceCubesApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/IceCubesApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -1,5 +1,14 @@
{
"pins" : [
+ {
+ "identity" : "apollo-ios",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apollographql/apollo-ios.git",
+ "state" : {
+ "revision" : "fdb97fe7016edc10dd217e530864dd3eee0f114b",
+ "version" : "1.7.0"
+ }
+ },
{
"identity" : "bodega",
"kind" : "remoteSourceControl",
@@ -14,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/Dean151/ButtonKit",
"state" : {
- "revision" : "377f5bab4ed047704316d531e0826d4de5ebf6a4",
- "version" : "0.1.1"
+ "revision" : "d4ed31ead81d04165591148f80bd2e56688bdbd7",
+ "version" : "0.1.2"
}
},
{
@@ -36,6 +45,15 @@
"version" : "2.2.7"
}
},
+ {
+ "identity" : "glean-swift",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/mozilla/glean-swift",
+ "state" : {
+ "revision" : "63e6475bd275399b701951925c64fd4c9a5f7c2d",
+ "version" : "54.0.0"
+ }
+ },
{
"identity" : "keychain-swift",
"kind" : "remoteSourceControl",
@@ -54,6 +72,15 @@
"version" : "1.3.2"
}
},
+ {
+ "identity" : "lottie-spm",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/airbnb/lottie-spm.git",
+ "state" : {
+ "revision" : "96790253c1a82223bd43da651121abfd7e96d0f3",
+ "version" : "4.3.4"
+ }
+ },
{
"identity" : "lrucache",
"kind" : "remoteSourceControl",
@@ -63,6 +90,15 @@
"version" : "1.0.4"
}
},
+ {
+ "identity" : "mozilla-social-ios",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/MozillaSocial/mozilla-social-ios",
+ "state" : {
+ "branch" : "ios17",
+ "revision" : "68ed7ae56d73da0b18894717d3c81172c9eae588"
+ }
+ },
{
"identity" : "nuke",
"kind" : "remoteSourceControl",
diff --git a/IceCubesApp/App/Tabs/Tabs.swift b/IceCubesApp/App/Tabs/Tabs.swift
index 49f1aa74..183d40ed 100644
--- a/IceCubesApp/App/Tabs/Tabs.swift
+++ b/IceCubesApp/App/Tabs/Tabs.swift
@@ -15,6 +15,7 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
case post
case followedTags
case lists
+ case discover
nonisolated var id: Int {
rawValue
@@ -69,6 +70,10 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
}
case .post:
VStack { }
+ case .discover:
+ NavigationTab {
+ Text("Todays Top Picks, Coming Soon!")
+ }
case .other:
EmptyView()
}
@@ -78,7 +83,7 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
var label: some View {
switch self {
case .timeline:
- Label("tab.timeline", systemImage: iconName)
+ Image(systemName: iconName)
case .trending:
Label("tab.trending", systemImage: iconName)
case .local:
@@ -86,7 +91,7 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
case .federated:
Label("tab.federated", systemImage: iconName)
case .notifications:
- Label("tab.notifications", systemImage: iconName)
+ Image(systemName: iconName)
case .mentions:
Label("tab.mentions", systemImage: iconName)
case .explore:
@@ -96,17 +101,19 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
case .settings:
Label("tab.settings", systemImage: iconName)
case .profile:
- Label("tab.profile", systemImage: iconName)
+ Image(systemName: iconName)
case .bookmarks:
Label("accessibility.tabs.profile.picker.bookmarks", systemImage: iconName)
case .favorites:
Label("accessibility.tabs.profile.picker.favorites", systemImage: iconName)
case .post:
- Label("menu.new-post", systemImage: iconName)
+ Image(iconName)
case .followedTags:
Label("timeline.filter.tags", systemImage: iconName)
case .lists:
Label("timeline.filter.lists", systemImage: iconName)
+ case .discover:
+ Image(systemName: iconName)
case .other:
EmptyView()
@@ -116,7 +123,7 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
var iconName: String {
switch self {
case .timeline:
- "rectangle.stack"
+ "house"
case .trending:
"chart.line.uptrend.xyaxis"
case .local:
@@ -140,11 +147,13 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
case .favorites:
"star"
case .post:
- "square.and.pencil"
+ "hexagonPlus"
case .followedTags:
"tag"
case .lists:
"list.bullet"
+ case .discover:
+ "safari"
case .other:
""
}
@@ -204,9 +213,9 @@ class iOSTabs {
class Storage {
@AppStorage(TabEntries.first.rawValue) var firstTab = Tab.timeline
- @AppStorage(TabEntries.second.rawValue) var secondTab = Tab.notifications
- @AppStorage(TabEntries.third.rawValue) var thirdTab = Tab.explore
- @AppStorage(TabEntries.fourth.rawValue) var fourthTab = Tab.messages
+ @AppStorage(TabEntries.second.rawValue) var secondTab = Tab.discover
+ @AppStorage(TabEntries.third.rawValue) var thirdTab = Tab.post
+ @AppStorage(TabEntries.fourth.rawValue) var fourthTab = Tab.notifications
@AppStorage(TabEntries.fifth.rawValue) var fifthTab = Tab.profile
}
diff --git a/IceCubesApp/App/Tabs/Timeline/TimelineTab.swift b/IceCubesApp/App/Tabs/Timeline/TimelineTab.swift
index 8f703750..8534fb7d 100644
--- a/IceCubesApp/App/Tabs/Timeline/TimelineTab.swift
+++ b/IceCubesApp/App/Tabs/Timeline/TimelineTab.swift
@@ -49,6 +49,13 @@ struct TimelineTab: View {
.withAppRouter()
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
.toolbar {
+ ToolbarItem(placement: .navigation){
+ Image("mozillaLogo")
+ .resizable()
+ .frame(width: 96, height: 27)
+ .padding(.vertical, 10)
+ }
+
toolbarView
}
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
diff --git a/IceCubesApp/App/Tabs/ToolbarTab.swift b/IceCubesApp/App/Tabs/ToolbarTab.swift
index ff36b40d..abe6c915 100644
--- a/IceCubesApp/App/Tabs/ToolbarTab.swift
+++ b/IceCubesApp/App/Tabs/ToolbarTab.swift
@@ -2,6 +2,7 @@ import SwiftUI
import Env
import AppAccount
import DesignSystem
+import Explore
@MainActor
struct ToolbarTab: ToolbarContent {
@@ -11,17 +12,16 @@ struct ToolbarTab: ToolbarContent {
@Environment(UserPreferences.self) private var userPreferences
@Binding var routerPath: RouterPath
-
+ @State private var scrollToTopSignal: Int = 0
+
var body: some ToolbarContent {
if !isSecondaryColumn {
- statusEditorToolbarItem(routerPath: routerPath,
- visibility: userPreferences.postVisibility)
- if UIDevice.current.userInterfaceIdiom != .pad ||
- (UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .compact) {
- ToolbarItem(placement: .navigationBarLeading) {
- AppAccountsSelectorView(routerPath: routerPath)
+ ToolbarItem {
+ NavigationLink(destination: ExploreView(scrollToTopSignal: $scrollToTopSignal)) {
+ Image(systemName: "magnifyingglass")
+ .foregroundStyle(Theme.shared.labelColor)
+ }
}
- }
}
if UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .regular {
if (!isSecondaryColumn && !userPreferences.showiPadSecondaryColumn) || isSecondaryColumn {
diff --git a/IceCubesApp/Assets.xcassets/HexagonPlus.imageset/Contents.json b/IceCubesApp/Assets.xcassets/HexagonPlus.imageset/Contents.json
new file mode 100644
index 00000000..41d13234
--- /dev/null
+++ b/IceCubesApp/Assets.xcassets/HexagonPlus.imageset/Contents.json
@@ -0,0 +1,26 @@
+{
+ "images" : [
+ {
+ "filename" : "HexagonPlus.svg",
+ "idiom" : "universal"
+ },
+ {
+ "appearances" : [
+ {
+ "appearance" : "luminosity",
+ "value" : "dark"
+ }
+ ],
+ "filename" : "HexagonPlusDarkMode.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "compression-type" : "automatic",
+ "template-rendering-intent" : "original"
+ }
+}
diff --git a/IceCubesApp/Assets.xcassets/HexagonPlus.imageset/HexagonPlus.svg b/IceCubesApp/Assets.xcassets/HexagonPlus.imageset/HexagonPlus.svg
new file mode 100644
index 00000000..d8fc07eb
--- /dev/null
+++ b/IceCubesApp/Assets.xcassets/HexagonPlus.imageset/HexagonPlus.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/IceCubesApp/Assets.xcassets/HexagonPlus.imageset/HexagonPlusDarkMode.svg b/IceCubesApp/Assets.xcassets/HexagonPlus.imageset/HexagonPlusDarkMode.svg
new file mode 100644
index 00000000..2388fc9a
--- /dev/null
+++ b/IceCubesApp/Assets.xcassets/HexagonPlus.imageset/HexagonPlusDarkMode.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/IceCubesApp/Assets.xcassets/mozillaLogo.imageset/Contents.json b/IceCubesApp/Assets.xcassets/mozillaLogo.imageset/Contents.json
new file mode 100644
index 00000000..e06b095b
--- /dev/null
+++ b/IceCubesApp/Assets.xcassets/mozillaLogo.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "filename" : "mozillaLogo.pdf",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "preserves-vector-representation" : true
+ }
+}
diff --git a/IceCubesApp/Assets.xcassets/mozillaLogo.imageset/mozillaLogo.pdf b/IceCubesApp/Assets.xcassets/mozillaLogo.imageset/mozillaLogo.pdf
new file mode 100644
index 00000000..5b8268a5
--- /dev/null
+++ b/IceCubesApp/Assets.xcassets/mozillaLogo.imageset/mozillaLogo.pdf
@@ -0,0 +1,194 @@
+%PDF-1.7
+
+1 0 obj
+ << >>
+endobj
+
+2 0 obj
+ << /Length 3 0 R >>
+stream
+/DeviceRGB CS
+/DeviceRGB cs
+q
+1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
+0.000000 0.000000 0.000000 scn
+0.000000 40.000000 m
+140.529633 40.000000 l
+140.529633 0.000000 l
+0.000000 0.000000 l
+0.000000 40.000000 l
+h
+f
+n
+Q
+q
+1.000000 0.000000 -0.000000 1.000000 8.340332 7.833496 cm
+1.000000 1.000000 1.000000 scn
+125.879425 3.455029 m
+125.605675 3.378027 125.373596 3.336029 125.142036 3.336029 c
+124.319763 3.336029 123.933502 3.686029 123.933502 4.693029 c
+123.933502 12.296528 l
+123.933502 16.290028 120.736328 18.234531 116.955986 18.234531 c
+114.067741 18.234531 112.515625 17.884531 109.430473 16.647030 c
+108.742317 12.618029 l
+112.754219 12.191528 l
+113.323326 14.164028 l
+114.145599 14.590528 114.960838 14.667528 116.014168 14.667528 c
+118.860222 14.667528 118.902412 12.534028 118.902412 10.750528 c
+118.902412 10.170528 l
+118.003288 10.289028 116.991150 10.324028 116.014168 10.324028 c
+112.002266 10.324028 107.828621 9.317028 107.828621 5.008528 c
+107.828621 1.364527 110.709343 0.000526 113.245979 0.000526 c
+116.091530 0.000526 117.883247 1.707027 118.895386 3.490528 c
+119.126953 1.357527 120.412849 0.000526 122.753090 0.000526 c
+123.842079 0.000526 124.973274 0.308027 125.907555 0.819027 c
+125.879425 3.455528 l
+125.879425 3.455029 l
+h
+115.086914 3.567028 m
+113.568954 3.567028 113.020935 4.462029 113.020935 5.588530 c
+113.020935 7.491030 114.581093 7.994528 116.372818 7.994528 c
+117.188057 7.994528 118.087181 7.875528 118.909454 7.763529 c
+118.789902 4.847029 116.878639 3.567028 115.086914 3.567028 c
+115.086914 3.567028 l
+h
+108.334450 27.082031 m
+100.731567 0.384527 l
+95.778343 0.384527 l
+103.380722 27.081532 l
+108.334450 27.081532 l
+108.334450 27.082031 l
+h
+98.125107 27.082031 m
+90.522232 0.384527 l
+85.575546 0.384527 l
+93.178421 27.081532 l
+98.125107 27.081532 l
+98.125107 27.082031 l
+h
+77.017288 17.884029 m
+82.280434 17.884029 l
+82.280434 11.603529 l
+77.017288 11.603529 l
+77.017288 17.884029 l
+77.017288 17.884029 l
+h
+77.017288 6.672529 m
+82.280434 6.672529 l
+82.280434 0.384527 l
+77.017288 0.384527 l
+77.017288 6.672529 l
+h
+69.358658 6.903528 m
+73.335403 6.518528 l
+72.246407 0.384527 l
+56.886440 0.384527 l
+56.380627 3.021526 l
+66.048973 14.079529 l
+60.554268 14.079529 l
+59.774689 11.365528 l
+56.148560 11.757528 l
+56.773926 17.891029 l
+72.211243 17.891029 l
+72.605042 15.254529 l
+62.851810 4.189529 l
+68.543411 4.189529 l
+69.358658 6.903528 l
+69.358658 6.903528 l
+h
+44.168610 18.233532 m
+37.851635 18.233532 34.732319 14.002528 34.732319 8.882528 c
+34.732319 3.294027 38.477001 0.000027 43.894352 0.000027 c
+49.508602 0.000027 53.563198 3.532028 53.563198 9.120029 c
+53.563198 14.009530 50.478554 18.234032 44.168610 18.234032 c
+44.168610 18.233532 l
+h
+44.049061 3.840029 m
+41.323055 3.840029 39.917606 6.169027 39.917606 9.197529 c
+39.917606 12.498529 41.512428 14.394030 44.091759 14.394030 c
+46.466148 14.394030 48.377415 12.806529 48.377415 9.274029 c
+48.377415 5.938028 46.663052 3.840029 44.049061 3.840029 c
+h
+30.207062 4.189529 m
+32.546795 4.189529 l
+32.546795 0.384527 l
+25.175985 0.384527 l
+25.175985 10.239529 l
+25.175985 13.268029 24.164345 14.429529 22.175722 14.429529 c
+19.758635 14.429529 18.782156 12.722528 18.782156 10.274529 c
+18.782156 4.189529 l
+21.121889 4.189529 l
+21.121889 0.384527 l
+13.758110 0.384527 l
+13.758110 10.239529 l
+13.758110 13.268029 12.745967 14.429529 10.757848 14.429529 c
+8.340760 14.429529 7.363779 12.722528 7.363779 10.274529 c
+7.363779 4.189529 l
+10.715654 4.189529 l
+10.715654 0.384527 l
+0.000000 0.384527 l
+0.000000 4.189529 l
+2.340235 4.189529 l
+2.340235 14.086529 l
+0.000000 14.086529 l
+0.000000 17.891529 l
+7.363779 17.891529 l
+7.363779 15.254529 l
+8.418115 17.114529 10.252028 18.241032 12.704276 18.241032 c
+15.240912 18.241032 17.573612 17.038029 18.437576 14.478029 c
+19.414558 16.807030 21.402676 18.241032 24.171377 18.241032 c
+27.325846 18.241032 30.214094 16.338530 30.214094 12.191029 c
+30.214094 4.189529 l
+30.207062 4.189529 l
+h
+f
+n
+Q
+
+endstream
+endobj
+
+3 0 obj
+ 3949
+endobj
+
+4 0 obj
+ << /Annots []
+ /Type /Page
+ /MediaBox [ 0.000000 0.000000 140.529602 40.000000 ]
+ /Resources 1 0 R
+ /Contents 2 0 R
+ /Parent 5 0 R
+ >>
+endobj
+
+5 0 obj
+ << /Kids [ 4 0 R ]
+ /Count 1
+ /Type /Pages
+ >>
+endobj
+
+6 0 obj
+ << /Pages 5 0 R
+ /Type /Catalog
+ >>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000010 00000 n
+0000000034 00000 n
+0000004039 00000 n
+0000004062 00000 n
+0000004236 00000 n
+0000004310 00000 n
+trailer
+<< /ID [ (some) (id) ]
+ /Root 6 0 R
+ /Size 7
+>>
+startxref
+4369
+%%EOF
\ No newline at end of file
diff --git a/IceCubesApp/Resources/Localization/Localizable.xcstrings b/IceCubesApp/Resources/Localization/Localizable.xcstrings
index c55a1a70..9c189c69 100644
--- a/IceCubesApp/Resources/Localization/Localizable.xcstrings
+++ b/IceCubesApp/Resources/Localization/Localizable.xcstrings
@@ -72365,6 +72365,7 @@
}
},
"tab.notifications" : {
+ "extractionState" : "stale",
"localizations" : {
"be" : {
"stringUnit" : {
@@ -72483,6 +72484,7 @@
}
},
"tab.profile" : {
+ "extractionState" : "stale",
"localizations" : {
"be" : {
"stringUnit" : {
@@ -76430,6 +76432,9 @@
}
}
}
+ },
+ "Todays Top Picks, Coming Soon!" : {
+
}
},
"version" : "1.0"
diff --git a/Packages/DesignSystem/Sources/DesignSystem/ColorSet.swift b/Packages/DesignSystem/Sources/DesignSystem/ColorSet.swift
index 60dd6042..32947af1 100644
--- a/Packages/DesignSystem/Sources/DesignSystem/ColorSet.swift
+++ b/Packages/DesignSystem/Sources/DesignSystem/ColorSet.swift
@@ -7,7 +7,8 @@ public let availableColorsSets: [ColorSetCouple] =
.init(light: NemesisLight(), dark: NemesisDark()),
.init(light: MediumLight(), dark: MediumDark()),
.init(light: ConstellationLight(), dark: ConstellationDark()),
- .init(light: ThreadsLight(), dark: ThreadsDark())]
+ .init(light: ThreadsLight(), dark: ThreadsDark()),
+ .init(light: MozillaLight(), dark: MozillaDark())]
public protocol ColorSet {
var name: ColorSetName { get }
@@ -37,6 +38,8 @@ public enum ColorSetName: String {
case constellationDark = "Constellation - Dark"
case threadsLight = "Threads - Light"
case threadsDark = "Threads - Dark"
+ case mozillaLight = "Mozilla - Light"
+ case mozillaDark = "Mozilla - Dark"
}
public struct ColorSetCouple: Identifiable {
@@ -202,3 +205,25 @@ public struct ThreadsLight: ColorSet {
public init() {}
}
+public struct MozillaLight: ColorSet {
+ public var name: ColorSetName = .mozillaLight
+ public var scheme: ColorScheme = .light
+ public var tintColor: Color = .init(hex: 0x7542E5)
+ public var primaryBackgroundColor: Color = .init(hex: 0xFFFFFF)
+ public var secondaryBackgroundColor: Color = .init(hex: 0xFFFFFF)
+ public var labelColor: Color = .black
+
+ public init() {}
+}
+
+public struct MozillaDark: ColorSet {
+ public var name: ColorSetName = .mozillaDark
+ public var scheme: ColorScheme = .dark
+ public var tintColor: Color = .init(hex: 0xCB9EFF)
+ public var primaryBackgroundColor: Color = .init(hex: 0x101010)
+ public var secondaryBackgroundColor: Color = .init(hex: 0x181818)
+ public var labelColor: Color = .init(hex: 0xE2E4E2)
+
+ public init() {}
+}
+
diff --git a/Packages/DesignSystem/Sources/DesignSystem/Theme.swift b/Packages/DesignSystem/Sources/DesignSystem/Theme.swift
index 6961544a..2fc89fe1 100644
--- a/Packages/DesignSystem/Sources/DesignSystem/Theme.swift
+++ b/Packages/DesignSystem/Sources/DesignSystem/Theme.swift
@@ -310,7 +310,9 @@ import SwiftUI
ConstellationLight(),
ConstellationDark(),
ThreadsLight(),
- ThreadsDark()
+ ThreadsDark(),
+ MozillaLight(),
+ MozillaDark()
]
}
diff --git a/Packages/Models/Sources/Models/Alias/ServerDate.swift b/Packages/Models/Sources/Models/Alias/ServerDate.swift
index 986e19d4..c75f803d 100644
--- a/Packages/Models/Sources/Models/Alias/ServerDate.swift
+++ b/Packages/Models/Sources/Models/Alias/ServerDate.swift
@@ -14,8 +14,8 @@ public struct ServerDate: Codable, Hashable, Equatable, Sendable {
return DateFormatterCache.shared.createdAtRelativeFormatter.localizedString(for: date,
relativeTo: Date())
} else {
- return Duration.seconds(-date.timeIntervalSinceNow).formatted(.units(width: .narrow,
- maximumUnitCount: 1))
+ return Duration.seconds(-date.timeIntervalSinceNow).formatted(.units(width: .wide,
+ maximumUnitCount: 1)) + " ago"
}
}
diff --git a/Packages/StatusKit/Sources/StatusKit/Row/StatusActionButtonStyle.swift b/Packages/StatusKit/Sources/StatusKit/Row/StatusActionButtonStyle.swift
index 8370d81f..ddeac080 100644
--- a/Packages/StatusKit/Sources/StatusKit/Row/StatusActionButtonStyle.swift
+++ b/Packages/StatusKit/Sources/StatusKit/Row/StatusActionButtonStyle.swift
@@ -18,7 +18,6 @@ struct StatusActionButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
- .foregroundColor(isOn ? tintColor : Color(UIColor.secondaryLabel))
.animation(nil, value: isOn)
.brightness(brightness(configuration: configuration))
.animation(configuration.isPressed ? nil : .default, value: isOn)
diff --git a/Packages/StatusKit/Sources/StatusKit/Row/StatusRowView.swift b/Packages/StatusKit/Sources/StatusKit/Row/StatusRowView.swift
index 2e9e1e8b..19a65a87 100644
--- a/Packages/StatusKit/Sources/StatusKit/Row/StatusRowView.swift
+++ b/Packages/StatusKit/Sources/StatusKit/Row/StatusRowView.swift
@@ -35,6 +35,10 @@ public struct StatusRowView: View {
StatusRowContextMenu(viewModel: viewModel, showTextForSelection: $showSelectableText)
}
+ var headerView: some View {
+ StatusRowHeaderView(showTextForSelection: $showSelectableText, viewModel: viewModel)
+ }
+
public var body: some View {
HStack(spacing: 0) {
if !isCompact {
@@ -61,12 +65,9 @@ public struct StatusRowView: View {
}
} else {
if !isCompact && context != .detail {
- Group {
StatusRowTagView(viewModel: viewModel)
StatusRowReblogView(viewModel: viewModel)
StatusRowReplyView(viewModel: viewModel)
- }
- .padding(.leading, theme.avatarPosition == .top ? 0 : AvatarView.FrameConfig.status.width + .statusColumnsSpacing)
}
HStack(alignment: .top, spacing: .statusColumnsSpacing) {
if !isCompact,
@@ -80,7 +81,7 @@ public struct StatusRowView: View {
}
VStack(alignment: .leading, spacing: .statusComponentSpacing) {
if !isCompact {
- StatusRowHeaderView(viewModel: viewModel)
+ headerView
}
StatusRowContentView(viewModel: viewModel)
.contentShape(Rectangle())
diff --git a/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowActionsView.swift b/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowActionsView.swift
index a3bae1fc..00dfe745 100644
--- a/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowActionsView.swift
+++ b/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowActionsView.swift
@@ -28,12 +28,13 @@ struct StatusRowActionsView: View {
}
var actions: [Action] {
- switch theme.statusActionSecondary {
- case .share:
- return [.respond, .boost, .favorite, .share, .menu]
- case .bookmark:
- return [.respond, .boost, .favorite, .bookmark, .menu]
- }
+// switch theme.statusActionSecondary {
+// case .share:
+// return [.respond, .boost, .favorite, .share, .menu]
+// case .bookmark:
+// return [.respond, .boost, .favorite, .bookmark, .menu]
+// }
+ [.respond, .boost, .favorite, .share]
}
@MainActor
@@ -43,7 +44,7 @@ struct StatusRowActionsView: View {
func image(dataController: StatusDataController, privateBoost: Bool = false) -> Image {
switch self {
case .respond:
- return Image(systemName: "arrowshape.turn.up.left")
+ return Image(systemName: "bubble.left.and.bubble.right")
case .boost:
if privateBoost {
if dataController.isReblogged {
@@ -52,9 +53,9 @@ struct StatusRowActionsView: View {
return Image(systemName: "lock.rotation")
}
}
- return Image(dataController.isReblogged ? "Rocket.Fill" : "Rocket")
+ return Image(systemName: dataController.isReblogged ? "arrow.2.squarepath" : "arrow.2.squarepath")
case .favorite:
- return Image(systemName: dataController.isFavorited ? "star.fill" : "star")
+ return Image(systemName: dataController.isFavorited ? "heart.fill" : "heart")
case .bookmark:
return Image(systemName: dataController.isBookmarked ? "bookmark.fill" : "bookmark")
case .share:
@@ -171,27 +172,9 @@ struct StatusRowActionsView: View {
.accessibilityLabel("status.action.share-link")
}
}
- Spacer()
- } else if action == .menu {
- Menu {
- StatusRowContextMenu(viewModel: viewModel, showTextForSelection: $showTextForSelection)
- .onAppear {
- Task {
- await viewModel.loadAuthorRelationship()
- }
- }
- } label: {
- Label("", systemImage: "ellipsis")
- .padding(.vertical, 6)
- }
- .menuStyle(.button)
- .buttonStyle(.borderless)
- .foregroundStyle(.secondary)
- .contentShape(Rectangle())
- .accessibilityLabel("status.action.context-menu")
} else {
- actionButton(action: action)
- Spacer()
+ actionButton(action: action)
+ Spacer()
}
}
}
@@ -207,17 +190,10 @@ struct StatusRowActionsView: View {
handleAction(action: action)
} label: {
HStack(spacing: 2) {
- if action == .boost {
- action
- .image(dataController: statusDataController, privateBoost: privateBoost())
- .imageScale(.medium)
- .font(.scaledBody)
- .fontWeight(.black)
- } else {
- action
- .image(dataController: statusDataController, privateBoost: privateBoost())
- .font(.scaledBody)
- }
+ action
+ .image(dataController: statusDataController, privateBoost: privateBoost())
+ .font(.scaledBody)
+
if !isNarrow,
let count = action.count(dataController: statusDataController,
isFocused: isFocused,
@@ -227,7 +203,7 @@ struct StatusRowActionsView: View {
.lineLimit(1)
.minimumScaleFactor(0.6)
.contentTransition(.numericText(value: Double(count)))
- .foregroundColor(Color(UIColor.secondaryLabel))
+ .foregroundColor(.black)
.font(.scaledFootnote)
.monospacedDigit()
.opacity(count > 0 ? 1 : 0)
diff --git a/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowHeaderView.swift b/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowHeaderView.swift
index b4226a6b..102eb13c 100644
--- a/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowHeaderView.swift
+++ b/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowHeaderView.swift
@@ -12,19 +12,42 @@ struct StatusRowHeaderView: View {
@Environment(Theme.self) private var theme
+ @Binding var showTextForSelection: Bool
+
let viewModel: StatusRowViewModel
var body: some View {
- HStack(alignment: theme.avatarPosition == .top ? .center : .top) {
- Button {
- viewModel.navigateToAccountDetail(account: viewModel.finalStatus.account)
- } label: {
- accountView
+ HStack()
+ {
+ VStack(alignment: .leading, spacing: 0) {
+ Button {
+ viewModel.navigateToAccountDetail(account: viewModel.finalStatus.account)
+ } label: {
+ accountView
+ }
+ .buttonStyle(.plain)
+
+ if !redactionReasons.contains(.placeholder) {
+ dateView
+ }
}
- .buttonStyle(.plain)
Spacer()
- if !redactionReasons.contains(.placeholder) {
- dateView
+
+ Menu {
+ StatusRowContextMenu(viewModel: viewModel, showTextForSelection: $showTextForSelection)
+ .onAppear {
+ Task {
+ await viewModel.loadAuthorRelationship()
+ }
+ }
+ } label: {
+ Label("", systemImage: "ellipsis")
+ .foregroundStyle(Theme.shared.labelColor)
+ .padding(.vertical, 6)
}
+ .menuStyle(.button)
+ .buttonStyle(.borderless)
+ .contentShape(Rectangle())
+ .accessibilityLabel("status.action.context-menu")
}
.accessibilityElement(children: .combine)
.accessibilityLabel(Text("\(viewModel.finalStatus.account.safeDisplayName)") + Text(", ") + Text(viewModel.finalStatus.createdAt.relativeFormatted))
@@ -45,7 +68,6 @@ struct StatusRowHeaderView: View {
Group {
EmojiTextApp(.init(stringValue: viewModel.finalStatus.account.safeDisplayName),
emojis: viewModel.finalStatus.account.emojis)
- .font(.scaledSubheadline)
.foregroundColor(theme.labelColor)
.emojiSize(Font.scaledSubheadlineFont.emojiSize)
.emojiBaselineOffset(Font.scaledSubheadlineFont.emojiBaselineOffset)
@@ -85,12 +107,11 @@ struct StatusRowHeaderView: View {
private var dateView: some View {
Group {
- Text(Image(systemName: viewModel.finalStatus.visibility.iconName)) +
- Text(" βΈ± ") +
- Text(viewModel.finalStatus.createdAt.relativeFormatted)
+ Text(viewModel.finalStatus.createdAt.relativeFormatted) +
+ Text(" - ") +
+ Text("@\(viewModel.finalStatus.account.acct)")
}
- .font(.scaledFootnote)
.foregroundStyle(.secondary)
- .lineLimit(1)
+ .lineLimit(2)
}
}
diff --git a/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowReblogView.swift b/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowReblogView.swift
index 08e8325a..27e66f7b 100644
--- a/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowReblogView.swift
+++ b/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowReblogView.swift
@@ -7,8 +7,7 @@ struct StatusRowReblogView: View {
var body: some View {
if viewModel.status.reblog != nil {
HStack(spacing: 2) {
- Image("Rocket.Fill")
- AvatarView(viewModel.status.account.avatar, config: .boost)
+ Image(systemName: "arrow.2.squarepath")
EmojiTextApp(.init(stringValue: viewModel.status.account.safeDisplayName), emojis: viewModel.status.account.emojis)
Text("status.row.was-boosted")
}
@@ -21,7 +20,6 @@ struct StatusRowReblogView: View {
.font(.scaledFootnote)
.emojiSize(Font.scaledFootnoteFont.emojiSize)
.emojiBaselineOffset(Font.scaledFootnoteFont.emojiBaselineOffset)
- .foregroundStyle(.secondary)
.fontWeight(.semibold)
.onTapGesture {
viewModel.navigateToAccountDetail(account: viewModel.status.account)
diff --git a/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowReplyView.swift b/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowReplyView.swift
index 162670f0..72623c2e 100644
--- a/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowReplyView.swift
+++ b/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowReplyView.swift
@@ -34,7 +34,6 @@ struct StatusRowReplyView: View {
}
}
.font(.scaledFootnote)
- .foregroundStyle(.secondary)
.fontWeight(.semibold)
}
}
diff --git a/Packages/Timeline/Sources/Timeline/TimelineFilter.swift b/Packages/Timeline/Sources/Timeline/TimelineFilter.swift
index 3cb808d5..db6862ee 100644
--- a/Packages/Timeline/Sources/Timeline/TimelineFilter.swift
+++ b/Packages/Timeline/Sources/Timeline/TimelineFilter.swift
@@ -30,7 +30,6 @@ public enum RemoteTimelineFilter: String, CaseIterable, Hashable, Equatable {
}
public enum TimelineFilter: Hashable, Equatable, Identifiable {
-
case home, local, federated, trending
case hashtag(tag: String, accountId: String?)
case tagGroup(title: String, tags: [String], symbolName: String?)
@@ -39,10 +38,14 @@ public enum TimelineFilter: Hashable, Equatable, Identifiable {
case latest
case resume
+ public static var mozillaFilters: [TimelineFilter] {
+ [.home, .local, .federated,]
+ }
+
public var id: String {
title
}
-
+
public func hash(into hasher: inout Hasher) {
hasher.combine(title)
}
diff --git a/Packages/Timeline/Sources/Timeline/View/TimelineView.swift b/Packages/Timeline/Sources/Timeline/View/TimelineView.swift
index 72fdfe61..257d67fc 100644
--- a/Packages/Timeline/Sources/Timeline/View/TimelineView.swift
+++ b/Packages/Timeline/Sources/Timeline/View/TimelineView.swift
@@ -1,4 +1,5 @@
import Charts
+import DesignKit
import DesignSystem
import Env
import Models
@@ -25,6 +26,8 @@ public struct TimelineView: View {
@State private var wasBackgrounded: Bool = false
@State private var collectionView: UICollectionView?
+ @State private var selectedTimelineFilter: LocalizedStringKey
+
@Binding var timeline: TimelineFilter
@Binding var pinnedFilters: [TimelineFilter]
@Binding var selectedTagGroup: TagGroup?
@@ -45,15 +48,28 @@ public struct TimelineView: View {
_selectedTagGroup = selectedTagGroup
_scrollToTopSignal = scrollToTopSignal
self.canFilterTimeline = canFilterTimeline
+ _selectedTimelineFilter = State(initialValue: TimelineFilter.mozillaFilters.first!.localizedTitle())
}
public var body: some View {
+ SegmentedControl(sources: TimelineFilter.mozillaFilters.map { $0.localizedTitle() }, selected: $selectedTimelineFilter)
+ .onChange(of: selectedTimelineFilter) { newValue in
+ if let selectedTimeline = TimelineFilter.mozillaFilters.first(where: { $0.localizedTitle() == newValue }) {
+ self.timeline = selectedTimeline
+ }
+ }
ScrollViewReader { proxy in
ZStack(alignment: .top) {
List {
scrollToTopView
TimelineTagGroupheaderView(group: $selectedTagGroup, timeline: $timeline)
+ .background {
+ Color.red
+ }
TimelineTagHeaderView(tag: $viewModel.tag)
+ .background {
+ Color.blue
+ }
switch viewModel.timeline {
case .remoteLocal:
StatusesListView(fetcher: viewModel, client: client, routerPath: routerPath, isRemote: true)
@@ -110,7 +126,6 @@ public struct TimelineView: View {
}
}
.toolbar {
- toolbarTitleView
toolbarTagGroupButton
}
.navigationBarTitleDisplayMode(.inline)