mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-11 21:55:04 +00:00
3d85480944
* ui: onboarding assets * android: fix gradle version check, pass assets dir to builds * desktop: pass assets dir to gradle builds * ui: new onboarding (#6872) * ios: improve onboarding * ios version condition * android strings * merge keys * refactor network conditions to old location * ios scroll headline * remove nav view * kotlin: refactor network commitments page to use existing view * remove unused keys * update why page * configure -> setup * padding for app bar in why page * fix why page * padding * copy translations from the website * export localizations * export again * kotlin: fix why page * fix * import localizations * custom layout * padding for system bars * paddings * more paddings * more padding 2 * update fonts * fonts * line height, padding * paddings * refactor notifications * refactor ios * notification icons in cards * restore profile field * padding * desktop layout create profile * fix * more layout * create profile layout * mobile padding * split mobile and desktop * layout * layout * background * refactor onboarding images * use DARK theme by default * page 3 and 4 layouts * restructure desktop onboarding to two panes * improve layout * improve * fonts, padding * link mobile on full page * fix, reduce noise * change to animation * fix animation * refactor * colors, animation * import * details * fix padding * fix icon * fix * button paddings * accept button on terms page * fix conditions button * close modal --------- Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Co-authored-by: shum <github.shum@liber.li> Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
194 lines
6.7 KiB
Swift
194 lines
6.7 KiB
Swift
//
|
|
// YourNetwork.swift
|
|
// SimpleX (iOS)
|
|
//
|
|
// Created by Evgeny on 22/04/2026.
|
|
// Copyright © 2026 SimpleX Chat. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import SimpleXChat
|
|
|
|
private enum YourNetworkSheet: Identifiable {
|
|
case configureOperators
|
|
case configureNotifications
|
|
|
|
var id: String {
|
|
switch self {
|
|
case .configureOperators: return "configureOperators"
|
|
case .configureNotifications: return "configureNotifications"
|
|
}
|
|
}
|
|
}
|
|
|
|
struct YourNetworkView: View {
|
|
@EnvironmentObject var theme: AppTheme
|
|
@Environment(\.colorScheme) var colorScheme: ColorScheme
|
|
@State private var serverOperators: [ServerOperator] = []
|
|
@State private var selectedOperatorIds = Set<Int64>()
|
|
@State private var notificationMode: NotificationsMode = .instant
|
|
@State private var sheetItem: YourNetworkSheet? = nil
|
|
@State private var nextStepNavLinkActive = false
|
|
@State private var justOpened = true
|
|
|
|
var body: some View {
|
|
GeometryReader { g in
|
|
VStack(alignment: .center, spacing: 10) {
|
|
Spacer(minLength: 0)
|
|
|
|
#if SIMPLEX_ASSETS
|
|
Image(colorScheme == .light ? "your-network" : "your-network-light")
|
|
.resizable()
|
|
.scaledToFit()
|
|
.frame(maxWidth: .infinity)
|
|
#else
|
|
ZStack {
|
|
let gp = OnboardingCardView.gradientPoints(aspectRatio: 1.0, scale: colorScheme == .light ? 1.2 : 1.5)
|
|
LinearGradient(
|
|
stops: colorScheme == .light ? OnboardingCardView.lightStops : OnboardingCardView.darkStops,
|
|
startPoint: gp.start,
|
|
endPoint: gp.end
|
|
)
|
|
Image(systemName: "network")
|
|
.font(.system(size: 72))
|
|
.foregroundColor(theme.colors.primary)
|
|
}
|
|
.aspectRatio(1.0, contentMode: .fit)
|
|
.clipShape(RoundedRectangle(cornerRadius: 24))
|
|
.padding(.horizontal, 25)
|
|
.frame(maxWidth: .infinity)
|
|
#endif
|
|
|
|
Text("Your network")
|
|
.font(.largeTitle)
|
|
.bold()
|
|
.multilineTextAlignment(.center)
|
|
.fixedSize(horizontal: false, vertical: true)
|
|
.padding(.top, 15)
|
|
|
|
Text("Network routers cannot know\nwho talks to whom")
|
|
.font(.title3)
|
|
.fontWeight(.medium)
|
|
.foregroundColor(theme.colors.secondary)
|
|
.multilineTextAlignment(.center)
|
|
.fixedSize(horizontal: false, vertical: true)
|
|
|
|
VStack(alignment: .leading, spacing: 20) {
|
|
configureRoutersButton()
|
|
configureNotificationsButton()
|
|
}
|
|
.padding(.top, 15)
|
|
.padding(.bottom, 15)
|
|
|
|
Spacer(minLength: 0)
|
|
|
|
continueButton()
|
|
.padding(.bottom, g.safeAreaInsets.bottom == 0 ? 20 : 0)
|
|
}
|
|
.padding(.horizontal, 25)
|
|
.padding(.top, 8)
|
|
.padding(.bottom, 20)
|
|
.frame(minHeight: g.size.height)
|
|
}
|
|
.onAppear {
|
|
if justOpened {
|
|
serverOperators = ChatModel.shared.conditions.serverOperators
|
|
selectedOperatorIds = Set(serverOperators.filter { $0.enabled }.map { $0.operatorId })
|
|
justOpened = false
|
|
}
|
|
}
|
|
.sheet(item: $sheetItem) { item in
|
|
switch item {
|
|
case .configureOperators:
|
|
ChooseServerOperators(serverOperators: serverOperators, selectedOperatorIds: $selectedOperatorIds)
|
|
.modifier(ThemedBackground())
|
|
case .configureNotifications:
|
|
SetNotificationsMode(notificationMode: $notificationMode)
|
|
.modifier(ThemedBackground())
|
|
}
|
|
}
|
|
.frame(maxHeight: .infinity)
|
|
.navigationBarHidden(true)
|
|
}
|
|
|
|
private func configureRoutersButton() -> some View {
|
|
Button {
|
|
sheetItem = .configureOperators
|
|
} label: {
|
|
HStack(spacing: 6) {
|
|
Text("Setup routers")
|
|
.fontWeight(.medium)
|
|
ForEach(serverOperators.reversed()) { op in
|
|
Image(op.logo(colorScheme))
|
|
.resizable()
|
|
.scaledToFit()
|
|
.frame(width: 22, height: 22)
|
|
.grayscale(selectedOperatorIds.contains(op.operatorId) ? 0.0 : 1.0)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func configureNotificationsButton() -> some View {
|
|
Button {
|
|
sheetItem = .configureNotifications
|
|
} label: {
|
|
HStack(spacing: 4) {
|
|
Text("Setup notifications")
|
|
.fontWeight(.medium)
|
|
Image(systemName: notificationMode.icon)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func continueButton() -> some View {
|
|
ZStack {
|
|
Button {
|
|
applyNotificationMode()
|
|
onboardingStageDefault.set(.step4_NetworkCommitments)
|
|
nextStepNavLinkActive = true
|
|
} label: {
|
|
Text("Continue")
|
|
}
|
|
.buttonStyle(OnboardingButtonStyle())
|
|
|
|
NavigationLink(isActive: $nextStepNavLinkActive) {
|
|
OnboardingConditionsView(selectedOperatorIds: selectedOperatorIds)
|
|
.navigationBarBackButtonHidden(true)
|
|
.modifier(ThemedBackground())
|
|
} label: {
|
|
EmptyView()
|
|
}
|
|
.frame(width: 1, height: 1)
|
|
.hidden()
|
|
}
|
|
}
|
|
|
|
private func applyNotificationMode() {
|
|
let m = ChatModel.shared
|
|
if let token = m.deviceToken {
|
|
switch notificationMode {
|
|
case .off:
|
|
m.tokenStatus = .new
|
|
m.notificationMode = .off
|
|
default:
|
|
Task {
|
|
do {
|
|
let status = try await apiRegisterToken(token: token, notificationMode: notificationMode)
|
|
await MainActor.run {
|
|
m.tokenStatus = status
|
|
m.notificationMode = notificationMode
|
|
}
|
|
} catch let error {
|
|
let a = getErrorAlert(error, "Error enabling notifications")
|
|
AlertManager.shared.showAlertMsg(
|
|
title: a.title,
|
|
message: a.message
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|