mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-29 04:39:53 +00:00
ios: different user picker layout (#4826)
* ios: different user picker layout * remove section * layout, color * color * remove activeUser * fix gradient * recursive sheets * gradient padding * share sheet * layout * dismiss sheets --------- Co-authored-by: Levitating Pineapple <noreply@levitatingpineapple.com>
This commit is contained in:
parent
8263106e19
commit
bb8bf0c8b2
7 changed files with 245 additions and 165 deletions
|
@ -38,6 +38,7 @@ struct IncomingCallView: View {
|
||||||
}
|
}
|
||||||
HStack {
|
HStack {
|
||||||
ProfilePreview(profileOf: invitation.contact, color: .white)
|
ProfilePreview(profileOf: invitation.contact, color: .white)
|
||||||
|
.padding(.vertical, 6)
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
callButton("Reject", "phone.down.fill", .red) {
|
callButton("Reject", "phone.down.fill", .red) {
|
||||||
|
|
|
@ -16,7 +16,6 @@ enum UserPickerSheet: Identifiable {
|
||||||
case currentProfile
|
case currentProfile
|
||||||
case useFromDesktop
|
case useFromDesktop
|
||||||
case settings
|
case settings
|
||||||
case userPicker
|
|
||||||
|
|
||||||
var id: Self { self }
|
var id: Self { self }
|
||||||
}
|
}
|
||||||
|
@ -32,7 +31,8 @@ struct ChatListView: View {
|
||||||
@State private var searchChatFilteredBySimplexLink: String? = nil
|
@State private var searchChatFilteredBySimplexLink: String? = nil
|
||||||
@State private var scrollToSearchBar = false
|
@State private var scrollToSearchBar = false
|
||||||
@State private var activeUserPickerSheet: UserPickerSheet? = nil
|
@State private var activeUserPickerSheet: UserPickerSheet? = nil
|
||||||
|
@State private var isUserPickerPresented: Bool = false
|
||||||
|
|
||||||
@AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false
|
@AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false
|
||||||
@AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true
|
@AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true
|
||||||
@AppStorage(DEFAULT_ONE_HAND_UI_CARD_SHOWN) private var oneHandUICardShown = false
|
@AppStorage(DEFAULT_ONE_HAND_UI_CARD_SHOWN) private var oneHandUICardShown = false
|
||||||
|
@ -58,44 +58,43 @@ struct ChatListView: View {
|
||||||
destination: chatView
|
destination: chatView
|
||||||
) { chatListView }
|
) { chatListView }
|
||||||
}
|
}
|
||||||
.sheet(item: $activeUserPickerSheet) { sheet in
|
.sheet(isPresented: $isUserPickerPresented) {
|
||||||
if let currentUser = chatModel.currentUser {
|
UserPicker(activeSheet: $activeUserPickerSheet)
|
||||||
switch sheet {
|
.sheet(item: $activeUserPickerSheet) { sheet in
|
||||||
case .address:
|
if let currentUser = chatModel.currentUser {
|
||||||
NavigationView {
|
switch sheet {
|
||||||
UserAddressView(shareViaProfile: currentUser.addressShared)
|
case .address:
|
||||||
.navigationTitle("Public address")
|
NavigationView {
|
||||||
|
UserAddressView(shareViaProfile: currentUser.addressShared)
|
||||||
|
.navigationTitle("Public address")
|
||||||
|
.navigationBarTitleDisplayMode(.large)
|
||||||
|
.modifier(ThemedBackground(grouped: true))
|
||||||
|
}
|
||||||
|
case .chatProfiles:
|
||||||
|
NavigationView {
|
||||||
|
UserProfilesView()
|
||||||
|
}
|
||||||
|
case .currentProfile:
|
||||||
|
NavigationView {
|
||||||
|
UserProfile()
|
||||||
|
.navigationTitle("Your current profile")
|
||||||
|
.modifier(ThemedBackground())
|
||||||
|
}
|
||||||
|
case .chatPreferences:
|
||||||
|
NavigationView {
|
||||||
|
PreferencesView(profile: currentUser.profile, preferences: currentUser.fullPreferences, currentPreferences: currentUser.fullPreferences)
|
||||||
|
.navigationTitle("Your preferences")
|
||||||
|
.navigationBarTitleDisplayMode(.large)
|
||||||
|
.modifier(ThemedBackground(grouped: true))
|
||||||
|
}
|
||||||
|
case .useFromDesktop:
|
||||||
|
ConnectDesktopView(viaSettings: false)
|
||||||
|
case .settings:
|
||||||
|
SettingsView(showSettings: $showSettings)
|
||||||
.navigationBarTitleDisplayMode(.large)
|
.navigationBarTitleDisplayMode(.large)
|
||||||
.modifier(ThemedBackground(grouped: true))
|
|
||||||
}
|
}
|
||||||
case .chatProfiles:
|
|
||||||
NavigationView {
|
|
||||||
UserProfilesView()
|
|
||||||
}
|
|
||||||
case .currentProfile:
|
|
||||||
NavigationView {
|
|
||||||
UserProfile()
|
|
||||||
.navigationTitle("Your current profile")
|
|
||||||
.modifier(ThemedBackground())
|
|
||||||
}
|
|
||||||
case .chatPreferences:
|
|
||||||
NavigationView {
|
|
||||||
PreferencesView(profile: currentUser.profile, preferences: currentUser.fullPreferences, currentPreferences: currentUser.fullPreferences)
|
|
||||||
.navigationTitle("Your preferences")
|
|
||||||
.navigationBarTitleDisplayMode(.large)
|
|
||||||
.modifier(ThemedBackground(grouped: true))
|
|
||||||
}
|
|
||||||
case .useFromDesktop:
|
|
||||||
ConnectDesktopView(viaSettings: false)
|
|
||||||
case .settings:
|
|
||||||
SettingsView(showSettings: $showSettings)
|
|
||||||
.navigationBarTitleDisplayMode(.large)
|
|
||||||
case .userPicker:
|
|
||||||
UserPicker(
|
|
||||||
activeSheet: $activeUserPickerSheet
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +207,7 @@ struct ChatListView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
activeUserPickerSheet = .userPicker
|
isUserPickerPresented = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +297,7 @@ struct ChatListView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func unreadBadge(_ text: Text? = Text(" "), size: CGFloat = 18) -> some View {
|
private func unreadBadge(size: CGFloat = 18) -> some View {
|
||||||
Circle()
|
Circle()
|
||||||
.frame(width: size, height: size)
|
.frame(width: size, height: size)
|
||||||
.foregroundColor(theme.colors.primary)
|
.foregroundColor(theme.colors.primary)
|
||||||
|
|
|
@ -9,102 +9,77 @@ import SimpleXChat
|
||||||
struct UserPicker: View {
|
struct UserPicker: View {
|
||||||
@EnvironmentObject var m: ChatModel
|
@EnvironmentObject var m: ChatModel
|
||||||
@EnvironmentObject var theme: AppTheme
|
@EnvironmentObject var theme: AppTheme
|
||||||
@Environment(\.scenePhase) var scenePhase
|
@Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.scenePhase) private var scenePhase: ScenePhase
|
||||||
|
@Environment(\.colorScheme) private var colorScheme: ColorScheme
|
||||||
|
@Environment(\.dismiss) private var dismiss: DismissAction
|
||||||
@Binding var activeSheet: UserPickerSheet?
|
@Binding var activeSheet: UserPickerSheet?
|
||||||
@State private var activeUser: User? = nil
|
@State private var switchingProfile = false
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
let v = List {
|
|
||||||
VStack(alignment: .leading, spacing: 6) {
|
|
||||||
if let currentUser = activeUser ?? m.currentUser {
|
|
||||||
HStack(alignment: .top) {
|
|
||||||
ProfileImage(imageStr: currentUser.image, size: 52)
|
|
||||||
.onTapGesture {
|
|
||||||
activeSheet = .currentProfile
|
|
||||||
}
|
|
||||||
Spacer()
|
|
||||||
let usersToPreview = m.users.filter({ u in !u.user.hidden && u.user.userId != currentUser.userId })
|
|
||||||
ZStack(alignment: .leading) {
|
|
||||||
ZStack(alignment: .trailing) {
|
|
||||||
let ps = HStack(spacing: 20) {
|
|
||||||
Color.clear.frame(width: 48, height: 32)
|
|
||||||
ForEach(usersToPreview) { u in
|
|
||||||
userView(u)
|
|
||||||
}
|
|
||||||
Color.clear.frame(width: 32, height: 32)
|
|
||||||
}
|
|
||||||
|
|
||||||
if usersToPreview.count > 3 {
|
|
||||||
let s = ScrollView(.horizontal) { ps }.frame(width: 284)
|
|
||||||
if #available(iOS 16.0, *) {
|
|
||||||
s.scrollIndicators(.hidden)
|
|
||||||
} else {
|
|
||||||
s
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ps
|
|
||||||
}
|
|
||||||
HStack(spacing: 0) {
|
|
||||||
LinearGradient(
|
|
||||||
colors: [.clear, theme.colors.background.asGroupedBackground(theme.base.mode)],
|
|
||||||
startPoint: .leading,
|
|
||||||
endPoint: .trailing
|
|
||||||
)
|
|
||||||
.frame(width: 32, height: 35)
|
|
||||||
Button {
|
|
||||||
activeSheet = .chatProfiles
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "ellipsis.circle.fill")
|
|
||||||
.resizable()
|
|
||||||
.scaledToFit()
|
|
||||||
.frame(width: 31, height: 31)
|
|
||||||
.padding(.top, 4)
|
|
||||||
.foregroundColor(Color(uiColor: .quaternaryLabel))
|
|
||||||
.modifier(ThemedBackground(grouped: true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.top, 10)
|
|
||||||
|
|
||||||
LinearGradient(
|
|
||||||
colors: [.clear, theme.colors.background.asGroupedBackground(theme.base.mode)],
|
|
||||||
startPoint: .trailing,
|
|
||||||
endPoint: .leading
|
|
||||||
)
|
|
||||||
.frame(width: 32, height: 35)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text(currentUser.displayName)
|
|
||||||
.fontWeight(.bold)
|
|
||||||
.font(.headline)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
|
||||||
.listRowBackground(Color.clear)
|
|
||||||
.listRowSeparator(.hidden)
|
|
||||||
.padding(.horizontal, 12)
|
|
||||||
|
|
||||||
Section {
|
var body: some View {
|
||||||
if (m.currentUser != nil) {
|
if #available(iOS 16.0, *) {
|
||||||
openSheetOnTap(title: m.userAddress == nil ? "Create public address" : "Your public address", image: "qrcode") {
|
let v = viewBody.presentationDetents([.height(420)])
|
||||||
|
if #available(iOS 16.4, *) {
|
||||||
|
v.scrollBounceBehavior(.basedOnSize)
|
||||||
|
} else {
|
||||||
|
v
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
viewBody
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var viewBody: some View {
|
||||||
|
let otherUsers = m.users.filter { u in !u.user.hidden && u.user.userId != m.currentUser?.userId }
|
||||||
|
return List {
|
||||||
|
Section(header: Text("You").foregroundColor(theme.colors.secondary)) {
|
||||||
|
if let user = m.currentUser {
|
||||||
|
openSheetOnTap(label: {
|
||||||
|
ZStack {
|
||||||
|
let v = ProfilePreview(profileOf: user)
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
.padding(.leading, -8)
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
v.padding(.vertical, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
activeSheet = .currentProfile
|
||||||
|
}
|
||||||
|
|
||||||
|
openSheetOnTap(title: m.userAddress == nil ? "Create public address" : "Your public address", icon: "qrcode") {
|
||||||
activeSheet = .address
|
activeSheet = .address
|
||||||
}
|
}
|
||||||
|
|
||||||
openSheetOnTap(title: "Chat preferences", image: "switch.2") {
|
openSheetOnTap(title: "Chat preferences", icon: "switch.2") {
|
||||||
activeSheet = .chatPreferences
|
activeSheet = .chatPreferences
|
||||||
}
|
}
|
||||||
|
|
||||||
openSheetOnTap(title: "Use from desktop", image: "desktopcomputer") {
|
|
||||||
activeSheet = .useFromDesktop
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
|
if otherUsers.isEmpty {
|
||||||
|
openSheetOnTap(title: "Your chat profiles", icon: "person.crop.rectangle.stack") {
|
||||||
|
activeSheet = .chatProfiles
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let v = userPickerRow(otherUsers, size: 44)
|
||||||
|
.padding(.leading, -8)
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
v.padding(.vertical, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openSheetOnTap(title: "Use from desktop", icon: "desktopcomputer") {
|
||||||
|
activeSheet = .useFromDesktop
|
||||||
|
}
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
openSheetOnTap(title: "Settings", image: "gearshape") {
|
openSheetOnTap(title: "Settings", icon: "gearshape") {
|
||||||
activeSheet = .settings
|
activeSheet = .settings
|
||||||
}
|
}
|
||||||
Label {} icon: {
|
Label {} icon: {
|
||||||
|
@ -146,33 +121,92 @@ struct UserPicker: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.modifier(ThemedBackground(grouped: true))
|
.modifier(ThemedBackground(grouped: true))
|
||||||
|
.disabled(switchingProfile)
|
||||||
if #available(iOS 16.0, *) {
|
}
|
||||||
v.presentationDetents([.height(400)])
|
|
||||||
} else {
|
private func userPickerRow(_ users: [UserInfo], size: CGFloat) -> some View {
|
||||||
v
|
HStack(spacing: 6) {
|
||||||
|
let s = ScrollView(.horizontal) {
|
||||||
|
HStack(spacing: 27) {
|
||||||
|
// Image(systemName: "person.crop.rectangle.stack.fill")
|
||||||
|
// .resizable()
|
||||||
|
// .scaledToFit()
|
||||||
|
// .frame(height: size)
|
||||||
|
// .foregroundColor(Color(uiColor: .tertiarySystemGroupedBackground).asAnotherColorFromSecondaryVariant(theme))
|
||||||
|
// .padding([.top, .trailing], 3)
|
||||||
|
// Image(systemName: "theatermasks.fill")
|
||||||
|
// .resizable()
|
||||||
|
// .scaledToFit()
|
||||||
|
// .frame(width: size, height: size)
|
||||||
|
// .foregroundColor(.indigo)
|
||||||
|
// .padding([.top, .trailing], 3)
|
||||||
|
ForEach(users) { u in
|
||||||
|
if !u.user.hidden && u.user.userId != m.currentUser?.userId {
|
||||||
|
userView(u, size: size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.leading, 2)
|
||||||
|
.padding(.trailing, 22)
|
||||||
|
}
|
||||||
|
ZStack {
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
s.scrollIndicators(.hidden)
|
||||||
|
} else {
|
||||||
|
s
|
||||||
|
}
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
LinearGradient(
|
||||||
|
colors: [.black, .clear],
|
||||||
|
startPoint: .leading,
|
||||||
|
endPoint: .trailing
|
||||||
|
)
|
||||||
|
.frame(width: 2)
|
||||||
|
Color.clear
|
||||||
|
LinearGradient(
|
||||||
|
colors: [.clear, .black],
|
||||||
|
startPoint: .leading,
|
||||||
|
endPoint: .trailing
|
||||||
|
)
|
||||||
|
.frame(width: size)
|
||||||
|
}
|
||||||
|
.frame(height: size + 3)
|
||||||
|
.blendMode(.destinationOut)
|
||||||
|
.allowsHitTesting(false)
|
||||||
|
}
|
||||||
|
.compositingGroup()
|
||||||
|
.padding(.top, -3) // to fit unread badge
|
||||||
|
Spacer()
|
||||||
|
Image(systemName: "chevron.right")
|
||||||
|
.foregroundColor(theme.colors.secondary)
|
||||||
|
.padding(.trailing, 4)
|
||||||
|
.onTapGesture {
|
||||||
|
activeSheet = .chatProfiles
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func userView(_ u: UserInfo) -> some View {
|
private func userView(_ u: UserInfo, size: CGFloat) -> some View {
|
||||||
ZStack(alignment: .topTrailing) {
|
ZStack(alignment: .topTrailing) {
|
||||||
ProfileImage(imageStr: u.user.image, size: 32, color: Color(uiColor: .quaternaryLabel))
|
ProfileImage(imageStr: u.user.image, size: size, color: Color(uiColor: .tertiarySystemGroupedBackground))
|
||||||
.padding([.top, .trailing], 3)
|
.padding([.top, .trailing], 3)
|
||||||
if (u.unreadCount > 0) {
|
if (u.unreadCount > 0) {
|
||||||
unreadBadge()
|
unreadBadge(u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.frame(width: size)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
activeUser = m.currentUser
|
switchingProfile = true
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
try await changeActiveUserAsync_(u.user.userId, viewPwd: nil)
|
try await changeActiveUserAsync_(u.user.userId, viewPwd: nil)
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
activeSheet = nil
|
switchingProfile = false
|
||||||
|
dismiss()
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
|
switchingProfile = false
|
||||||
AlertManager.shared.showAlertMsg(
|
AlertManager.shared.showAlertMsg(
|
||||||
title: "Error switching profile!",
|
title: "Error switching profile!",
|
||||||
message: "Error: \(responseError(error))"
|
message: "Error: \(responseError(error))"
|
||||||
|
@ -183,28 +217,34 @@ struct UserPicker: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func openSheetOnTap(title: LocalizedStringKey, image: String, setActive: @escaping () -> Void) -> some View {
|
private func openSheetOnTap(title: LocalizedStringKey, icon: String, action: @escaping () -> Void) -> some View {
|
||||||
Button(action: setActive) {
|
openSheetOnTap(label: {
|
||||||
Label {
|
ZStack(alignment: .leading) {
|
||||||
Text(title).foregroundColor(.primary)
|
Image(systemName: icon).frame(maxWidth: 24, maxHeight: 24, alignment: .center)
|
||||||
} icon: {
|
|
||||||
Image(systemName: image)
|
|
||||||
.resizable()
|
|
||||||
.symbolRenderingMode(.monochrome)
|
.symbolRenderingMode(.monochrome)
|
||||||
.foregroundColor(theme.colors.secondary)
|
.foregroundColor(theme.colors.secondary)
|
||||||
.frame(maxWidth: 20, maxHeight: 20)
|
Text(title)
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
.padding(.leading, 36)
|
||||||
}
|
}
|
||||||
}
|
}, action: action)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
.padding(.leading, 16).padding(.vertical, 8).padding(.trailing, 32)
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
.padding(.leading, -19).padding(.vertical, -8).padding(.trailing, -32)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func unreadBadge() -> some View {
|
private func openSheetOnTap<V: View>(label: () -> V, action: @escaping () -> Void) -> some View {
|
||||||
Circle()
|
Button(action: action, label: label)
|
||||||
.frame(width: 12, height: 12)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.foregroundColor(theme.colors.primary)
|
.contentShape(Rectangle())
|
||||||
|
}
|
||||||
|
|
||||||
|
private func unreadBadge(_ u: UserInfo) -> some View {
|
||||||
|
let size = dynamicSize(userFont).chatInfoSize
|
||||||
|
return unreadCountText(u.unreadCount)
|
||||||
|
.font(userFont <= .xxxLarge ? .caption : .caption2)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.padding(.horizontal, dynamicSize(userFont).unreadPadding)
|
||||||
|
.frame(minWidth: size, minHeight: size)
|
||||||
|
.background(u.user.showNtfs ? theme.colors.primary : theme.colors.secondary)
|
||||||
|
.cornerRadius(dynamicSize(userFont).unreadCorner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,3 +20,41 @@ func showShareSheet(items: [Any], completed: (() -> Void)? = nil) {
|
||||||
presentedViewController.present(activityViewController, animated: true)
|
presentedViewController.present(activityViewController, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension View {
|
||||||
|
func shareSheet(item: Binding<ShareItem?>) -> some View {
|
||||||
|
sheet(item: item) { item in
|
||||||
|
Group {
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
ActivityView(item: item)
|
||||||
|
.presentationDetents([.medium, .large])
|
||||||
|
} else {
|
||||||
|
ActivityView(item: item)
|
||||||
|
}
|
||||||
|
}.ignoresSafeArea()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ShareItem: Identifiable {
|
||||||
|
let content: any Hashable
|
||||||
|
var id: Int { content.hashValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct ActivityView: UIViewControllerRepresentable {
|
||||||
|
let item: ShareItem
|
||||||
|
|
||||||
|
func makeUIViewController(
|
||||||
|
context: UIViewControllerRepresentableContext<ActivityView>
|
||||||
|
) -> UIActivityViewController {
|
||||||
|
UIActivityViewController(
|
||||||
|
activityItems: [item.content],
|
||||||
|
applicationActivities: nil
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIViewController(
|
||||||
|
_ uiViewController: UIActivityViewController,
|
||||||
|
context: UIViewControllerRepresentableContext<ActivityView>
|
||||||
|
) { }
|
||||||
|
}
|
||||||
|
|
|
@ -504,17 +504,18 @@ struct ProfilePreview: View {
|
||||||
HStack {
|
HStack {
|
||||||
ProfileImage(imageStr: profileOf.image, size: 44, color: color)
|
ProfileImage(imageStr: profileOf.image, size: 44, color: color)
|
||||||
.padding(.trailing, 6)
|
.padding(.trailing, 6)
|
||||||
.padding(.vertical, 6)
|
profileName().lineLimit(1)
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text(profileOf.displayName)
|
|
||||||
.fontWeight(.bold)
|
|
||||||
.font(.title2)
|
|
||||||
if profileOf.fullName != "" && profileOf.fullName != profileOf.displayName {
|
|
||||||
Text(profileOf.fullName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func profileName() -> Text {
|
||||||
|
var t = Text(profileOf.displayName).fontWeight(.semibold).font(.title2)
|
||||||
|
if profileOf.fullName != "" && profileOf.fullName != profileOf.displayName {
|
||||||
|
t = t + Text(" (" + profileOf.fullName + ")")
|
||||||
|
// .font(.callout)
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SettingsView_Previews: PreviewProvider {
|
struct SettingsView_Previews: PreviewProvider {
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct UserAddressView: View {
|
||||||
@State private var mailViewResult: Result<MFMailComposeResult, Error>? = nil
|
@State private var mailViewResult: Result<MFMailComposeResult, Error>? = nil
|
||||||
@State private var alert: UserAddressAlert?
|
@State private var alert: UserAddressAlert?
|
||||||
@State private var progressIndicator = false
|
@State private var progressIndicator = false
|
||||||
|
@State private var shareItem: ShareItem?
|
||||||
@FocusState private var keyboardVisible: Bool
|
@FocusState private var keyboardVisible: Bool
|
||||||
|
|
||||||
private enum UserAddressAlert: Identifiable {
|
private enum UserAddressAlert: Identifiable {
|
||||||
|
@ -68,6 +69,7 @@ struct UserAddressView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.shareSheet(item: $shareItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Namespace private var bottomID
|
@Namespace private var bottomID
|
||||||
|
@ -245,7 +247,7 @@ struct UserAddressView: View {
|
||||||
|
|
||||||
private func shareQRCodeButton(_ userAddress: UserContactLink) -> some View {
|
private func shareQRCodeButton(_ userAddress: UserContactLink) -> some View {
|
||||||
Button {
|
Button {
|
||||||
showShareSheet(items: [simplexChatLink(userAddress.connReqContact)])
|
shareItem = ShareItem(content: simplexChatLink(userAddress.connReqContact))
|
||||||
} label: {
|
} label: {
|
||||||
settingsRow("square.and.arrow.up", color: theme.colors.secondary) {
|
settingsRow("square.and.arrow.up", color: theme.colors.secondary) {
|
||||||
Text("Share address")
|
Text("Share address")
|
||||||
|
|
|
@ -10,7 +10,6 @@ struct UserProfilesView: View {
|
||||||
@EnvironmentObject private var m: ChatModel
|
@EnvironmentObject private var m: ChatModel
|
||||||
@EnvironmentObject private var theme: AppTheme
|
@EnvironmentObject private var theme: AppTheme
|
||||||
@Environment(\.editMode) private var editMode
|
@Environment(\.editMode) private var editMode
|
||||||
@Environment(\.dismiss) var dismiss: DismissAction
|
|
||||||
@AppStorage(DEFAULT_SHOW_HIDDEN_PROFILES_NOTICE) private var showHiddenProfilesNotice = true
|
@AppStorage(DEFAULT_SHOW_HIDDEN_PROFILES_NOTICE) private var showHiddenProfilesNotice = true
|
||||||
@AppStorage(DEFAULT_SHOW_MUTE_PROFILE_ALERT) private var showMuteProfileAlert = true
|
@AppStorage(DEFAULT_SHOW_MUTE_PROFILE_ALERT) private var showMuteProfileAlert = true
|
||||||
@State private var showDeleteConfirmation = false
|
@State private var showDeleteConfirmation = false
|
||||||
|
@ -284,7 +283,7 @@ struct UserProfilesView: View {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
onboardingStageDefault.set(.step1_SimpleXInfo)
|
onboardingStageDefault.set(.step1_SimpleXInfo)
|
||||||
m.onboardingStage = .step1_SimpleXInfo
|
m.onboardingStage = .step1_SimpleXInfo
|
||||||
dismiss()
|
dismissAllSheets()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -307,7 +306,7 @@ struct UserProfilesView: View {
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
try await changeActiveUserAsync_(user.userId, viewPwd: userViewPassword(user))
|
try await changeActiveUserAsync_(user.userId, viewPwd: userViewPassword(user))
|
||||||
dismiss()
|
dismissAllSheets()
|
||||||
} catch {
|
} catch {
|
||||||
await MainActor.run { alert = .activateUserError(error: responseError(error)) }
|
await MainActor.run { alert = .activateUserError(error: responseError(error)) }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue