diff --git a/CoreData/ApplicationSettings+CoreDataProperties.swift b/CoreData/ApplicationSettings+CoreDataProperties.swift
index 3713f50..4263b4a 100644
--- a/CoreData/ApplicationSettings+CoreDataProperties.swift
+++ b/CoreData/ApplicationSettings+CoreDataProperties.swift
@@ -28,6 +28,7 @@ extension ApplicationSettings {
@NSManaged public var showSensitive: Bool
@NSManaged public var showPhotoDescription: Bool
+ @NSManaged public var menuPosition: Int32
}
extension ApplicationSettings: Identifiable {
diff --git a/CoreData/ApplicationSettingsHandler.swift b/CoreData/ApplicationSettingsHandler.swift
index 6e43340..f302c8c 100644
--- a/CoreData/ApplicationSettingsHandler.swift
+++ b/CoreData/ApplicationSettingsHandler.swift
@@ -107,6 +107,12 @@ class ApplicationSettingsHandler {
CoreDataHandler.shared.save()
}
+ func set(menuPosition: MenuPosition) {
+ let defaultSettings = self.get()
+ defaultSettings.menuPosition = Int32(menuPosition.rawValue)
+ CoreDataHandler.shared.save()
+ }
+
private func createApplicationSettingsEntity(viewContext: NSManagedObjectContext? = nil) -> ApplicationSettings {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
return ApplicationSettings(context: context)
diff --git a/CoreData/Vernissage.xcdatamodeld/.xccurrentversion b/CoreData/Vernissage.xcdatamodeld/.xccurrentversion
index c9463e5..caec0e4 100644
--- a/CoreData/Vernissage.xcdatamodeld/.xccurrentversion
+++ b/CoreData/Vernissage.xcdatamodeld/.xccurrentversion
@@ -3,6 +3,6 @@
_XCCurrentVersionName
- Vernissage-006.xcdatamodel
+ Vernissage-007.xcdatamodel
diff --git a/CoreData/Vernissage.xcdatamodeld/Vernissage-007.xcdatamodel/contents b/CoreData/Vernissage.xcdatamodeld/Vernissage-007.xcdatamodel/contents
new file mode 100644
index 0000000..2fbe9f3
--- /dev/null
+++ b/CoreData/Vernissage.xcdatamodeld/Vernissage-007.xcdatamodel/contents
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Localization/en.lproj/Localizable.strings b/Localization/en.lproj/Localizable.strings
index af4a9ee..5775a4e 100644
--- a/Localization/en.lproj/Localizable.strings
+++ b/Localization/en.lproj/Localizable.strings
@@ -204,6 +204,10 @@
"settings.title.sourceCode" = "Source code";
"settings.title.rate" = "Rate Vernissage";
"settings.title.socials" = "Socials";
+"settings.title.menuPosition" = "Menu position";
+"settings.title.topMenu" = "Navigation bar";
+"settings.title.bottomRightMenu" = "Bottom right";
+"settings.title.bottomLeftMenu" = "Bottom left";
// Mark: Signin view.
"signin.navigationBar.title" = "Sign in to Pixelfed";
diff --git a/Localization/eu.lproj/Localizable.strings b/Localization/eu.lproj/Localizable.strings
index d61663a..6aa069a 100644
--- a/Localization/eu.lproj/Localizable.strings
+++ b/Localization/eu.lproj/Localizable.strings
@@ -204,6 +204,10 @@
"settings.title.sourceCode" = "Iturburu kodea";
"settings.title.rate" = "Rate Vernissage";
"settings.title.socials" = "Socials";
+"settings.title.menuPosition" = "Menu position";
+"settings.title.topMenu" = "Navigation bar";
+"settings.title.bottomRightMenu" = "Bottom right";
+"settings.title.bottomLeftMenu" = "Bottom left";
// Mark: Signin view.
"signin.navigationBar.title" = "Hasi saioa Pixelfed-en";
diff --git a/Localization/pl.lproj/Localizable.strings b/Localization/pl.lproj/Localizable.strings
index 1439855..244e6b2 100644
--- a/Localization/pl.lproj/Localizable.strings
+++ b/Localization/pl.lproj/Localizable.strings
@@ -204,6 +204,10 @@
"settings.title.sourceCode" = "Kod źródłowy";
"settings.title.rate" = "Oceń Vernissage";
"settings.title.socials" = "Społeczności";
+"settings.title.menuPosition" = "Pozycja menu";
+"settings.title.topMenu" = "Panel tytułowy";
+"settings.title.bottomRightMenu" = "Dolny prawy";
+"settings.title.bottomLeftMenu" = "Dolny lewy";
// Mark: Signin view.
"signin.navigationBar.title" = "Zaloguj się do Pixelfed";
diff --git a/Models/MenuPosition.swift b/Models/MenuPosition.swift
new file mode 100644
index 0000000..26445cf
--- /dev/null
+++ b/Models/MenuPosition.swift
@@ -0,0 +1,13 @@
+//
+// https://mczachurski.dev
+// Copyright © 2023 Marcin Czachurski and the repository contributors.
+// Licensed under the Apache License 2.0.
+//
+
+import Foundation
+
+public enum MenuPosition: Int {
+ case top = 1
+ case bottomRight = 2
+ case bottomLeft = 3
+}
diff --git a/Vernissage.xcodeproj/project.pbxproj b/Vernissage.xcodeproj/project.pbxproj
index 81643b9..7c80233 100644
--- a/Vernissage.xcodeproj/project.pbxproj
+++ b/Vernissage.xcodeproj/project.pbxproj
@@ -146,6 +146,9 @@
F88FAD2B295F43B8009B20C9 /* AccountData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD29295F43B8009B20C9 /* AccountData+CoreDataProperties.swift */; };
F88FAD2D295F4AD7009B20C9 /* ApplicationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD2C295F4AD7009B20C9 /* ApplicationState.swift */; };
F88FAD32295F5029009B20C9 /* RemoteFileService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD31295F5029009B20C9 /* RemoteFileService.swift */; };
+ F8911A1729DE914D00770F44 /* NavigationMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8911A1629DE914D00770F44 /* NavigationMenu.swift */; };
+ F8911A1A29DEA0F500770F44 /* MenuPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8911A1929DEA0F500770F44 /* MenuPosition.swift */; };
+ F8911A1B29DEA0F500770F44 /* MenuPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8911A1929DEA0F500770F44 /* MenuPosition.swift */; };
F891E7CE29C35BF50022C449 /* ImageRowItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F891E7CD29C35BF50022C449 /* ImageRowItem.swift */; };
F891E7D029C368750022C449 /* ImageRowItemAsync.swift in Sources */ = {isa = PBXBuildFile; fileRef = F891E7CF29C368750022C449 /* ImageRowItemAsync.swift */; };
F897978829681B9C00B22335 /* UserAvatar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F897978729681B9C00B22335 /* UserAvatar.swift */; };
@@ -369,6 +372,9 @@
F88FAD29295F43B8009B20C9 /* AccountData+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountData+CoreDataProperties.swift"; sourceTree = ""; };
F88FAD2C295F4AD7009B20C9 /* ApplicationState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationState.swift; sourceTree = ""; };
F88FAD31295F5029009B20C9 /* RemoteFileService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteFileService.swift; sourceTree = ""; };
+ F8911A1629DE914D00770F44 /* NavigationMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationMenu.swift; sourceTree = ""; };
+ F8911A1829DE9E5500770F44 /* Vernissage-007.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-007.xcdatamodel"; sourceTree = ""; };
+ F8911A1929DEA0F500770F44 /* MenuPosition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuPosition.swift; sourceTree = ""; };
F891E7CD29C35BF50022C449 /* ImageRowItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRowItem.swift; sourceTree = ""; };
F891E7CF29C368750022C449 /* ImageRowItemAsync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRowItemAsync.swift; sourceTree = ""; };
F897978729681B9C00B22335 /* UserAvatar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAvatar.swift; sourceTree = ""; };
@@ -692,6 +698,7 @@
F86167C7297FE781004D1F67 /* AvatarShape.swift */,
F89D6C3E29716E41001DA3D4 /* Theme.swift */,
F87AEB932986C51B00434FB6 /* AppConstants.swift */,
+ F8911A1929DEA0F500770F44 /* MenuPosition.swift */,
);
path = Models;
sourceTree = "";
@@ -937,6 +944,7 @@
F8C5E56129892CC300ADF6A7 /* FirstAppear.swift */,
F8CAE63D29B8902D001E0372 /* ClearButton.swift */,
F8E9391E29C0BCFA002BB3B8 /* ImageContextMenu.swift */,
+ F8911A1629DE914D00770F44 /* NavigationMenu.swift */,
);
path = ViewModifiers;
sourceTree = "";
@@ -1140,6 +1148,7 @@
F864F77D29BB9A4600B13921 /* AttachmentData+CoreDataClass.swift in Sources */,
F864F7A629BBA01D00B13921 /* CoreDataError.swift in Sources */,
F864F77E29BB9A4900B13921 /* AttachmentData+CoreDataProperties.swift in Sources */,
+ F8911A1B29DEA0F500770F44 /* MenuPosition.swift in Sources */,
F864F78229BB9A6500B13921 /* StatusData+CoreDataClass.swift in Sources */,
F864F78329BB9A6800B13921 /* StatusData+CoreDataProperties.swift in Sources */,
F864F78429BB9A6E00B13921 /* ApplicationSettings+CoreDataClass.swift in Sources */,
@@ -1187,6 +1196,7 @@
F8864CF129ACFFB80020C534 /* View+Keyboard.swift in Sources */,
F88FAD21295F3944009B20C9 /* HomeFeedView.swift in Sources */,
F8FA991E299FAB92007AB130 /* PhotoEditorView.swift in Sources */,
+ F8911A1729DE914D00770F44 /* NavigationMenu.swift in Sources */,
F88C2475295C37BB0006098B /* CoreDataHandler.swift in Sources */,
F87AEB972986D16D00434FB6 /* AuthorisationError.swift in Sources */,
F8742FC429990AFB00E9642B /* ClientError.swift in Sources */,
@@ -1254,6 +1264,7 @@
F89A46DE296EABA20062125F /* StatusPlaceholderView.swift in Sources */,
F88C2482295C3A4F0006098B /* StatusView.swift in Sources */,
F866F6A329604161002E8F88 /* AccountDataHandler.swift in Sources */,
+ F8911A1A29DEA0F500770F44 /* MenuPosition.swift in Sources */,
F8996DEB2971D29D0043EEC6 /* View+Transition.swift in Sources */,
F876418B298AC1B80057D362 /* NoDataView.swift in Sources */,
F8E9392129C0DA7E002BB3B8 /* LazyImageState+ImageResponse.swift in Sources */,
@@ -1361,7 +1372,7 @@
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 94;
+ CURRENT_PROJECT_VERSION = 95;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageWidget/Info.plist;
@@ -1372,7 +1383,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 1.0.1;
+ MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@@ -1389,7 +1400,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 94;
+ CURRENT_PROJECT_VERSION = 95;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageWidget/Info.plist;
@@ -1400,7 +1411,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 1.0.1;
+ MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@@ -1537,7 +1548,7 @@
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 94;
+ CURRENT_PROJECT_VERSION = 95;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;
@@ -1554,7 +1565,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 1.0.1;
+ MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1577,7 +1588,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 94;
+ CURRENT_PROJECT_VERSION = 95;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;
@@ -1594,7 +1605,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 1.0.1;
+ MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -1731,6 +1742,7 @@
F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
+ F8911A1829DE9E5500770F44 /* Vernissage-007.xcdatamodel */,
F8EF371429C624DA00669F45 /* Vernissage-006.xcdatamodel */,
F8CAE64129B8F1AF001E0372 /* Vernissage-005.xcdatamodel */,
F8B05ACC29B48DD000857221 /* Vernissage-004.xcdatamodel */,
@@ -1739,7 +1751,7 @@
F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */,
F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */,
);
- currentVersion = F8EF371429C624DA00669F45 /* Vernissage-006.xcdatamodel */;
+ currentVersion = F8911A1829DE9E5500770F44 /* Vernissage-007.xcdatamodel */;
path = Vernissage.xcdatamodeld;
sourceTree = "";
versionGroupType = wrapper.xcdatamodel;
diff --git a/Vernissage/EnvironmentObjects/ApplicationState.swift b/Vernissage/EnvironmentObjects/ApplicationState.swift
index da4d9c4..6f90209 100644
--- a/Vernissage/EnvironmentObjects/ApplicationState.swift
+++ b/Vernissage/EnvironmentObjects/ApplicationState.swift
@@ -85,6 +85,9 @@ public class ApplicationState: ObservableObject {
/// Updated user profile.
@Published var updatedProfile: Account?
+ /// Information which menu should be shown (top or bottom).
+ @Published var menuPosition = MenuPosition.top
+
public func changeApplicationState(accountModel: AccountModel, instance: Instance?, lastSeenStatusId: String?) {
self.account = accountModel
self.lastSeenStatusId = lastSeenStatusId
diff --git a/Vernissage/VernissageApp.swift b/Vernissage/VernissageApp.swift
index 75cbbd9..4d49681 100644
--- a/Vernissage/VernissageApp.swift
+++ b/Vernissage/VernissageApp.swift
@@ -169,6 +169,10 @@ struct VernissageApp: App {
self.applicationState.showSensitive = defaultSettings.showSensitive
self.applicationState.showPhotoDescription = defaultSettings.showPhotoDescription
+ if let menuPosition = MenuPosition(rawValue: Int(defaultSettings.menuPosition)) {
+ self.applicationState.menuPosition = menuPosition
+ }
+
self.applicationState.hapticTabSelectionEnabled = defaultSettings.hapticTabSelectionEnabled
self.applicationState.hapticRefreshEnabled = defaultSettings.hapticRefreshEnabled
self.applicationState.hapticButtonPressEnabled = defaultSettings.hapticButtonPressEnabled
diff --git a/Vernissage/ViewModifiers/NavigationMenu.swift b/Vernissage/ViewModifiers/NavigationMenu.swift
new file mode 100644
index 0000000..3b73e0b
--- /dev/null
+++ b/Vernissage/ViewModifiers/NavigationMenu.swift
@@ -0,0 +1,74 @@
+//
+// https://mczachurski.dev
+// Copyright © 2023 Marcin Czachurski and the repository contributors.
+// Licensed under the Apache License 2.0.
+//
+
+import Foundation
+import SwiftUI
+
+public extension View {
+ func navigationMenu(menuPosition: Binding,
+ @ViewBuilder menuItems: @escaping () -> MenuItems) -> some View where MenuItems: View {
+ modifier(NavigationMenu(menuPosition: menuPosition, menuItems: menuItems))
+ }
+}
+
+private struct NavigationMenu: ViewModifier where MenuItems: View {
+
+ private let menuItems: () -> MenuItems
+
+ @Binding var menuPosition: MenuPosition
+
+ init(menuPosition: Binding, @ViewBuilder menuItems: @escaping () -> MenuItems) {
+ self.menuItems = menuItems
+ self._menuPosition = menuPosition
+ }
+
+ func body(content: Content) -> some View {
+ if self.menuPosition == .top {
+ content
+ } else {
+ ZStack {
+ content
+
+ VStack(alignment: .trailing) {
+ Spacer()
+ HStack {
+ if self.menuPosition == .bottomRight {
+ Spacer()
+
+ self.menuContent()
+ .padding(.trailing, 20)
+ }
+
+ if self.menuPosition == .bottomLeft {
+ self.menuContent()
+ .padding(.leading, 20)
+
+ Spacer()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @ViewBuilder
+ private func menuContent() -> some View {
+ Menu {
+ self.menuItems()
+ } label: {
+
+ Image(systemName: "line.3.horizontal.circle")
+ .resizable()
+ .foregroundColor(.mainTextColor.opacity(0.8))
+ .shadow(radius: 5)
+ .padding(8)
+ .frame(width: 44, height: 44)
+ .background(.ultraThinMaterial)
+ .clipShape(Circle())
+
+ }
+ }
+}
diff --git a/Vernissage/Views/MainView.swift b/Vernissage/Views/MainView.swift
index 060dd2c..2412349 100644
--- a/Vernissage/Views/MainView.swift
+++ b/Vernissage/Views/MainView.swift
@@ -32,21 +32,28 @@ struct MainView: View {
var body: some View {
self.getMainView()
- .navigationTitle(navBarTitle)
- .navigationBarTitleDisplayMode(.inline)
- .toolbar {
- self.getLeadingToolbar()
- self.getPrincipalToolbar()
- self.getTrailingToolbar()
- }
- .onChange(of: tipsStore.status) { status in
- if status == .successful {
- withAnimation(.spring()) {
- self.routerPath.presentedOverlay = .successPayment
- self.tipsStore.reset()
+ .navigationMenu(menuPosition: $applicationState.menuPosition) {
+ self.navigationMenuContent()
+ }
+ .navigationTitle(navBarTitle)
+ .navigationBarTitleDisplayMode(.inline)
+ .toolbar {
+ self.getLeadingToolbar()
+
+ if self.applicationState.menuPosition == .top {
+ self.getPrincipalToolbar()
+ }
+
+ self.getTrailingToolbar()
+ }
+ .onChange(of: tipsStore.status) { status in
+ if status == .successful {
+ withAnimation(.spring()) {
+ self.routerPath.presentedOverlay = .successPayment
+ self.tipsStore.reset()
+ }
}
}
- }
}
@ViewBuilder
@@ -92,97 +99,7 @@ struct MainView: View {
private func getPrincipalToolbar() -> some ToolbarContent {
ToolbarItem(placement: .principal) {
Menu {
- Button {
- self.switchView(to: .home)
- } label: {
- HStack {
- Text(self.getViewTitle(viewMode: .home))
- Image(systemName: "house")
- }
- }
-
- Button {
- self.switchView(to: .local)
- } label: {
- HStack {
- Text(self.getViewTitle(viewMode: .local))
- Image(systemName: "building")
- }
- }
-
- Button {
- self.switchView(to: .federated)
- } label: {
- HStack {
- Text(self.getViewTitle(viewMode: .federated))
- Image(systemName: "globe.europe.africa")
- }
- }
-
- Button {
- self.switchView(to: .search)
- } label: {
- HStack {
- Text(self.getViewTitle(viewMode: .search))
- Image(systemName: "magnifyingglass")
- }
- }
-
- Divider()
-
- Menu {
- Button {
- self.switchView(to: .trendingPhotos)
- } label: {
- HStack {
- Text(self.getViewTitle(viewMode: .trendingPhotos))
- Image(systemName: "photo.stack")
- }
- }
-
- Button {
- self.switchView(to: .trendingTags)
- } label: {
- HStack {
- Text(self.getViewTitle(viewMode: .trendingTags))
- Image(systemName: "tag")
- }
- }
-
- Button {
- self.switchView(to: .trendingAccounts)
- } label: {
- HStack {
- Text(self.getViewTitle(viewMode: .trendingAccounts))
- Image(systemName: "person.3")
- }
- }
- } label: {
- HStack {
- Text("mainview.tab.trending", comment: "Trending menu section")
- Image(systemName: "chart.line.uptrend.xyaxis")
- }
- }
-
- Divider()
-
- Button {
- self.switchView(to: .profile)
- } label: {
- HStack {
- Text(self.getViewTitle(viewMode: .profile))
- Image(systemName: "person.crop.circle")
- }
- }
-
- Button {
- self.switchView(to: .notifications)
- } label: {
- HStack {
- Text(self.getViewTitle(viewMode: .notifications))
- Image(systemName: "bell.badge")
- }
- }
+ self.navigationMenuContent()
} label: {
HStack {
Text(navBarTitle, comment: "Navbar title")
@@ -244,6 +161,101 @@ struct MainView: View {
}
}
+ @ViewBuilder
+ private func navigationMenuContent() -> some View {
+ Button {
+ self.switchView(to: .home)
+ } label: {
+ HStack {
+ Text(self.getViewTitle(viewMode: .home))
+ Image(systemName: "house")
+ }
+ }
+
+ Button {
+ self.switchView(to: .local)
+ } label: {
+ HStack {
+ Text(self.getViewTitle(viewMode: .local))
+ Image(systemName: "building")
+ }
+ }
+
+ Button {
+ self.switchView(to: .federated)
+ } label: {
+ HStack {
+ Text(self.getViewTitle(viewMode: .federated))
+ Image(systemName: "globe.europe.africa")
+ }
+ }
+
+ Button {
+ self.switchView(to: .search)
+ } label: {
+ HStack {
+ Text(self.getViewTitle(viewMode: .search))
+ Image(systemName: "magnifyingglass")
+ }
+ }
+
+ Divider()
+
+ Menu {
+ Button {
+ self.switchView(to: .trendingPhotos)
+ } label: {
+ HStack {
+ Text(self.getViewTitle(viewMode: .trendingPhotos))
+ Image(systemName: "photo.stack")
+ }
+ }
+
+ Button {
+ self.switchView(to: .trendingTags)
+ } label: {
+ HStack {
+ Text(self.getViewTitle(viewMode: .trendingTags))
+ Image(systemName: "tag")
+ }
+ }
+
+ Button {
+ self.switchView(to: .trendingAccounts)
+ } label: {
+ HStack {
+ Text(self.getViewTitle(viewMode: .trendingAccounts))
+ Image(systemName: "person.3")
+ }
+ }
+ } label: {
+ HStack {
+ Text("mainview.tab.trending", comment: "Trending menu section")
+ Image(systemName: "chart.line.uptrend.xyaxis")
+ }
+ }
+
+ Divider()
+
+ Button {
+ self.switchView(to: .profile)
+ } label: {
+ HStack {
+ Text(self.getViewTitle(viewMode: .profile))
+ Image(systemName: "person.crop.circle")
+ }
+ }
+
+ Button {
+ self.switchView(to: .notifications)
+ } label: {
+ HStack {
+ Text(self.getViewTitle(viewMode: .notifications))
+ Image(systemName: "bell.badge")
+ }
+ }
+ }
+
@ViewBuilder
private func getAvatarImage(avatarUrl: URL?, avatarData: Data?) -> some View {
if let avatarData,
diff --git a/Vernissage/Views/SettingsView/Subviews/GeneralSectionView.swift b/Vernissage/Views/SettingsView/Subviews/GeneralSectionView.swift
index aa7dfa4..e962294 100644
--- a/Vernissage/Views/SettingsView/Subviews/GeneralSectionView.swift
+++ b/Vernissage/Views/SettingsView/Subviews/GeneralSectionView.swift
@@ -29,6 +29,12 @@ struct GeneralSectionView: View {
(Theme.dark, "settings.title.dark")
]
+ private let menuPositions: [(menuPosition: MenuPosition, name: LocalizedStringKey)] = [
+ (MenuPosition.top, "settings.title.topMenu"),
+ (MenuPosition.bottomRight, "settings.title.bottomRightMenu"),
+ (MenuPosition.bottomLeft, "settings.title.bottomLeftMenu")
+ ]
+
var body: some View {
Section("settings.title.general") {
@@ -64,6 +70,20 @@ struct GeneralSectionView: View {
self.applicationState.theme = theme
ApplicationSettingsHandler.shared.set(theme: theme)
}
+
+ // Menu position.
+ Picker(selection: $applicationState.menuPosition) {
+ ForEach(self.menuPositions, id: \.menuPosition) { item in
+ Text(item.name, comment: "Menu positions")
+ .tag(item.menuPosition)
+ }
+ } label: {
+ Text("settings.title.menuPosition", comment: "Menu position")
+ }
+ .onChange(of: self.applicationState.menuPosition) { menuPosition in
+ self.applicationState.menuPosition = menuPosition
+ ApplicationSettingsHandler.shared.set(menuPosition: menuPosition)
+ }
}
}
}