Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ios-4104 New settings | 1st iteration of space edit screen #2753

Merged
merged 2 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions Anytype/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ internal enum Loc {
internal static let unsupportedBlock = Loc.tr("Localizable", "Unsupported block", fallback: "Unsupported block")
internal static let unsupportedDeeplink = Loc.tr("Localizable", "Unsupported deeplink", fallback: "Unsupported deeplink")
internal static let unsupportedValue = Loc.tr("Localizable", "Unsupported value", fallback: "Unsupported value")
internal static let untitled = Loc.tr("Localizable", "Untitled", fallback: "Untitled")
internal static let upgrade = Loc.tr("Localizable", "Upgrade", fallback: "Upgrade")
internal static let upload = Loc.tr("Localizable", "Upload", fallback: "Upload")
internal static let uploadPlayableAudio = Loc.tr("Localizable", "Upload playable audio", fallback: "Upload playable audio")
Expand Down Expand Up @@ -593,9 +594,6 @@ internal enum Loc {
}
}
internal enum BlockText {
internal enum Content {
internal static let placeholder = Loc.tr("Localizable", "BlockText.Content.Placeholder", fallback: "Untitled")
}
internal enum ContentType {
internal enum Bulleted {
internal static let placeholder = Loc.tr("Localizable", "BlockText.ContentType.Bulleted.Placeholder", fallback: "Bulleted list item")
Expand Down Expand Up @@ -1730,7 +1728,7 @@ internal enum Loc {
}
internal enum SpaceSettings {
internal static let deleteButton = Loc.tr("Localizable", "SpaceSettings.DeleteButton", fallback: "Delete space")
internal static let info = Loc.tr("Localizable", "SpaceSettings.Info", fallback: "Space info")
internal static let info = Loc.tr("Localizable", "SpaceSettings.Info", fallback: "Space information")
internal static let leaveButton = Loc.tr("Localizable", "SpaceSettings.LeaveButton", fallback: "Leave")
internal static let networkId = Loc.tr("Localizable", "SpaceSettings.NetworkId", fallback: "Network ID")
internal static let remoteStorage = Loc.tr("Localizable", "SpaceSettings.RemoteStorage", fallback: "Remote storage")
Expand Down
2 changes: 1 addition & 1 deletion Anytype/Resources/Strings/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"TextStyle.Link.Title" = "Link";

// MARK: - Block Text
"BlockText.Content.Placeholder" = "Untitled";

"BlockText.ContentType.Title.Placeholder" = "Untitled";
"BlockText.ContentType.Description.Placeholder" = "Add a description";
Expand Down Expand Up @@ -128,6 +127,7 @@
// MARK: - Mention
"Mention.Subtitle.Placeholder" = "Object";

"Untitled" = "Untitled";
"None" = "None";
"Callout" = "Callout";
"Toggle empty. Tap to create block." = "Toggle empty. Tap to create block.";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import SwiftUI


struct NavigationHeader<TitleView: View, RightView: View>: View {

@Environment(\.dismiss) var dismiss

@ViewBuilder
let titleView: TitleView
@ViewBuilder
let rightView: RightView

var body: some View {
NavigationHeaderContainer(spacing: 20) {
IncreaseTapButton {
dismiss()
} label: {
Image(asset: .X24.back)
.navPanelDynamicForegroundStyle()
}
} titleView: {
titleView
} rightView: {
rightView
}
.padding(.horizontal, 16)
.frame(height: PageNavigationHeaderConstants.height)
.background {
HomeBlurEffectView(direction: .topToBottom)
.ignoresSafeArea()
}
}
}

extension NavigationHeader where TitleView == AnyView {
init(title: String, @ViewBuilder rightView: () -> RightView) {
self.titleView = AnytypeText(title, style: .uxTitle1Semibold)
.foregroundColor(.Text.primary)
.frame(height: 48)
.lineLimit(1)
.eraseToAnyView()
self.rightView = rightView()
}
}

extension NavigationHeader where TitleView == AnyView, RightView == AnyView {
init(title: String) {
self.init(title: title, rightView: { EmptyView().eraseToAnyView() })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ final class SpaceSettingsCoordinatorViewModel: ObservableObject, SpaceSettingsMo

// MARK: - SpaceSettingsModuleOutput

func onSpaceDetailsSelected() {
anytypeAssertionFailure("\(#function) not supported in legacy module")
}

func onChangeIconSelected() {
showIconPickerSpaceId = workspaceInfo.accountSpaceId.identifiable
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct NewSpaceSettingsCoordinatorView: View {
}

var body: some View {
NewSpaceSettingsView(workspaceInfo: model.workspaceInfo, output: model)
navigation
.sheet(isPresented: $model.showRemoteStorage) {
RemoteStorageView(spaceId: model.accountSpaceId, output: model)
.sheet(isPresented: $model.showFiles) {
Expand Down Expand Up @@ -47,4 +47,16 @@ struct NewSpaceSettingsCoordinatorView: View {
dismiss()
}
}

private var navigation: some View {
NavigationStack(path: $model.path) {
NewSpaceSettingsView(workspaceInfo: model.workspaceInfo, output: model)
.navigationDestination(for: SpaceSettingsNavigationItem.self) { item in
switch item {
case .spaceDetails:
SpaceDetailsView(info: model.workspaceInfo, output: model)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import Combine
import AnytypeCore
import Services

enum SpaceSettingsNavigationItem {
case spaceDetails
}

@MainActor
final class NewSpaceSettingsCoordinatorViewModel: ObservableObject, SpaceSettingsModuleOutput, RemoteStorageModuleOutput, PersonalizationModuleOutput {

Expand All @@ -12,6 +16,8 @@ final class NewSpaceSettingsCoordinatorViewModel: ObservableObject, SpaceSetting
@Injected(\.documentService)
private var documentService: any OpenedDocumentsProviderProtocol

@Published var path = NavigationPath()

@Published var showRemoteStorage = false
@Published var showPersonalization = false
@Published var showWallpaperPicker = false
Expand All @@ -31,6 +37,10 @@ final class NewSpaceSettingsCoordinatorViewModel: ObservableObject, SpaceSetting

// MARK: - SpaceSettingsModuleOutput

func onSpaceDetailsSelected() {
path.append(SpaceSettingsNavigationItem.spaceDetails)
}

func onChangeIconSelected() {
showIconPickerSpaceId = workspaceInfo.accountSpaceId.identifiable
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ struct ObjectTypeView: View {
}, label: {
IconView(icon: model.details?.objectIconImage).frame(width: 32, height: 32)
})
TextField(Loc.BlockText.Content.placeholder, text: $model.typeName)
TextField(Loc.untitled, text: $model.typeName)
.foregroundColor(.Text.primary)
.font(AnytypeFontBuilder.font(anytypeFont: .title))
Spacer()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ struct NewSpaceSettingsView: View {
ScrollView(showsIndicators: false) {
VStack(spacing: 0) {

SettingsObjectHeader(name: $model.spaceName, nameTitle: Loc.Settings.spaceName, iconImage: model.spaceIcon, onTap: {
model.onChangeIconTap()
})
.disabled(!model.allowEditSpace)
spaceDetailsButton

spaceSection

Expand Down Expand Up @@ -101,6 +98,40 @@ struct NewSpaceSettingsView: View {
}
}

private var spaceDetailsButton: some View {
Button {
model.onSpaceDetailsTap()
} label: {
HStack(spacing: 0) {
if let icon = model.spaceIcon {
IconView(icon: icon)
.frame(width: 56, height: 56)
}

Spacer.fixedWidth(12)

VStack(alignment: .leading, spacing: 0) {
AnytypeText(model.spaceDisplayName, style: .bodySemibold)
Spacer.fixedHeight(2)
AnytypeText(model.spaceDisplayDescription, style: .uxTitle2Regular)
.foregroundColor(.Text.secondary)
}

Spacer.fixedWidth(12)

Spacer()

if model.allowEditSpace {
IconView(asset: .X24.Arrow.right)
.frame(width: 24, height: 24)
}
}
.padding(16)
.border(16, color: .Shape.primary, lineWidth: 0.5)
}
.disabled(!model.allowEditSpace)
}

@ViewBuilder
private var spaceSection: some View {
SectionHeaderView(title: Loc.Settings.spaceType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,23 @@ final class NewSpaceSettingsViewModel: ObservableObject {
// MARK: - State

let workspaceInfo: AccountInfo
private var subscriptions: [AnyCancellable] = []
private var dataLoaded = false
private var participantSpaceView: ParticipantSpaceViewData?
private var joiningCount: Int = 0
private var owner: Participant?

var spaceDisplayName: String {
spaceName.isNotEmpty ? spaceName : Loc.untitled
}

var spaceDisplayDescription: String {
spaceDescription.isNotEmpty ? spaceDescription : spaceAccessType
}

@Published var spaceName = ""
@Published var spaceDescription = ""
@Published var spaceAccessType = ""
@Published var spaceIcon: Icon?

@Published var info = [SettingsInfoModel]()
@Published var snackBarData = ToastBarData.empty
@Published var showSpaceDeleteAlert = false
Expand All @@ -58,6 +66,10 @@ final class NewSpaceSettingsViewModel: ObservableObject {
self.output = output
}

func onSpaceDetailsTap() {
output?.onSpaceDetailsSelected()
}

func onInfoTap() {
showInfoView.toggle()
}
Expand Down Expand Up @@ -124,6 +136,8 @@ final class NewSpaceSettingsViewModel: ObservableObject {

spaceIcon = spaceView.objectIconImage
spaceAccessType = spaceView.spaceAccessType?.name ?? ""
spaceName = spaceView.name
spaceDescription = spaceView.description
allowDelete = participantSpaceView.canBeDeleted
allowLeave = participantSpaceView.canLeave
allowEditSpace = participantSpaceView.canEdit
Expand Down Expand Up @@ -151,17 +165,6 @@ final class NewSpaceSettingsViewModel: ObservableObject {
} else {
shareSection = .member
}

if !dataLoaded {
spaceName = spaceView.name
dataLoaded = true
$spaceName
.delay(for: 0.3, scheduler: DispatchQueue.main)
.sink { [weak self] name in
self?.updateSpaceName(name: name)
}
.store(in: &subscriptions)
}
}

private func buildInfoBlock(details: SpaceView) {
Expand Down Expand Up @@ -207,13 +210,4 @@ final class NewSpaceSettingsViewModel: ObservableObject {
)
}
}

private func updateSpaceName(name: String) {
Task {
try await workspaceService.workspaceSetDetails(
spaceId: workspaceInfo.accountSpaceId,
details: [.name(name)]
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import Foundation

@MainActor
protocol SpaceSettingsModuleOutput: AnyObject {
func onSpaceDetailsSelected()

func onChangeIconSelected()
func onRemoteStorageSelected()
func onPersonalizationSelected()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import SwiftUI
import Services

struct SpaceDetailsView: View {
@StateObject private var model: SpaceDetailsViewModel

init(info: AccountInfo, output: any SpaceSettingsModuleOutput) {
_model = StateObject(wrappedValue: SpaceDetailsViewModel(info: info, output: output))
}

var body: some View {
content
.navigationBarHidden(true)
.task { await model.setupSubscriptions() }
}

private var content: some View {
VStack(spacing: 0) {
header
info
}
}

private var header: some View {
NavigationHeader(title: "") {
Button {
model.onSaveTap()
} label: {
AnytypeText(Loc.save, style: .bodyRegular)
}
}
}

private var info: some View {
VStack(spacing: 0) {
SettingsObjectHeader(name: $model.spaceName, nameTitle: Loc.Settings.spaceName, iconImage: model.spaceIcon, onTap: {
model.onChangeIconTap()
})
Spacer()
}.padding(.horizontal, 16)
}
}

Loading