add delete solo session
This commit is contained in:
		
							parent
							
								
									020aa8de5d
								
							
						
					
					
						commit
						854561b5f7
					
				@ -345,6 +345,9 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "Вы выйдете из выбранной сессии." : {
 | 
				
			||||||
 | 
					      "comment" : "Описание подтверждения завершения конкретной сессии"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "Вы выйдете со всех устройств, кроме текущего." : {
 | 
					    "Вы выйдете со всех устройств, кроме текущего." : {
 | 
				
			||||||
      "comment" : "Описание подтверждения завершения сессий"
 | 
					      "comment" : "Описание подтверждения завершения сессий"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -458,7 +461,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "Завершить" : {
 | 
					    "Завершить" : {
 | 
				
			||||||
      "comment" : "Подтверждение завершения других сессий"
 | 
					      "comment" : "Кнопка завершения конкретной сессии\nПодтверждение завершения других сессий\nПодтверждение завершения конкретной сессии"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "Завершить другие сессии" : {
 | 
					    "Завершить другие сессии" : {
 | 
				
			||||||
      "comment" : "Кнопка завершения других сессий"
 | 
					      "comment" : "Кнопка завершения других сессий"
 | 
				
			||||||
@ -466,6 +469,9 @@
 | 
				
			|||||||
    "Завершить сессии на других устройствах?" : {
 | 
					    "Завершить сессии на других устройствах?" : {
 | 
				
			||||||
      "comment" : "Заголовок подтверждения завершения сессий"
 | 
					      "comment" : "Заголовок подтверждения завершения сессий"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "Завершить эту сессию?" : {
 | 
				
			||||||
 | 
					      "comment" : "Заголовок подтверждения завершения отдельной сессии"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "Заглушка: Push-уведомления" : {
 | 
					    "Заглушка: Push-уведомления" : {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,8 @@ struct ActiveSessionsView: View {
 | 
				
			|||||||
    @State private var revokeInProgress = false
 | 
					    @State private var revokeInProgress = false
 | 
				
			||||||
    @State private var activeAlert: SessionsAlert?
 | 
					    @State private var activeAlert: SessionsAlert?
 | 
				
			||||||
    @State private var showRevokeConfirmation = false
 | 
					    @State private var showRevokeConfirmation = false
 | 
				
			||||||
 | 
					    @State private var sessionPendingRevoke: SessionViewData?
 | 
				
			||||||
 | 
					    @State private var revokingSessionIds: Set<UUID> = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private let sessionsService = SessionsService()
 | 
					    private let sessionsService = SessionsService()
 | 
				
			||||||
    private var currentSession: SessionViewData? {
 | 
					    private var currentSession: SessionViewData? {
 | 
				
			||||||
@ -60,7 +62,18 @@ struct ActiveSessionsView: View {
 | 
				
			|||||||
                if !otherSessions.isEmpty {
 | 
					                if !otherSessions.isEmpty {
 | 
				
			||||||
                    Section(header: Text(String(format: NSLocalizedString("Другие устройства (%d)", comment: "Заголовок секции других устройств с количеством"), otherSessions.count))) {
 | 
					                    Section(header: Text(String(format: NSLocalizedString("Другие устройства (%d)", comment: "Заголовок секции других устройств с количеством"), otherSessions.count))) {
 | 
				
			||||||
                        ForEach(otherSessions) { session in
 | 
					                        ForEach(otherSessions) { session in
 | 
				
			||||||
                            sessionRow(for: session)
 | 
					                            let isRevoking = isRevoking(session: session)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            sessionRow(for: session, isRevoking: isRevoking)
 | 
				
			||||||
 | 
					                                .swipeActions(edge: .trailing, allowsFullSwipe: false) {
 | 
				
			||||||
 | 
					                                    Button(role: .destructive) {
 | 
				
			||||||
 | 
					                                        sessionPendingRevoke = session
 | 
				
			||||||
 | 
					                                    } label: {
 | 
				
			||||||
 | 
					                                        Label(NSLocalizedString("Завершить", comment: "Кнопка завершения конкретной сессии"), systemImage: "trash")
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                    .disabled(isRevoking)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                .disabled(isRevoking)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -74,6 +87,24 @@ struct ActiveSessionsView: View {
 | 
				
			|||||||
        .refreshable {
 | 
					        .refreshable {
 | 
				
			||||||
            await loadSessions(force: true)
 | 
					            await loadSessions(force: true)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        .confirmationDialog(
 | 
				
			||||||
 | 
					            NSLocalizedString("Завершить эту сессию?", comment: "Заголовок подтверждения завершения отдельной сессии"),
 | 
				
			||||||
 | 
					            isPresented: Binding(
 | 
				
			||||||
 | 
					                get: { sessionPendingRevoke != nil },
 | 
				
			||||||
 | 
					                set: { if !$0 { sessionPendingRevoke = nil } }
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            presenting: sessionPendingRevoke
 | 
				
			||||||
 | 
					        ) { session in
 | 
				
			||||||
 | 
					            Button(NSLocalizedString("Завершить", comment: "Подтверждение завершения конкретной сессии"), role: .destructive) {
 | 
				
			||||||
 | 
					                sessionPendingRevoke = nil
 | 
				
			||||||
 | 
					                Task { await revoke(session: session) }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Button(NSLocalizedString("Отмена", comment: "Общий текст кнопки отмены"), role: .cancel) {
 | 
				
			||||||
 | 
					                sessionPendingRevoke = nil
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } message: { _ in
 | 
				
			||||||
 | 
					            Text(NSLocalizedString("Вы выйдете из выбранной сессии.", comment: "Описание подтверждения завершения конкретной сессии"))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        .alert(item: $activeAlert) { alert in
 | 
					        .alert(item: $activeAlert) { alert in
 | 
				
			||||||
            Alert(
 | 
					            Alert(
 | 
				
			||||||
                title: Text(alert.title),
 | 
					                title: Text(alert.title),
 | 
				
			||||||
@ -136,7 +167,7 @@ struct ActiveSessionsView: View {
 | 
				
			|||||||
        .listRowSeparator(.hidden)
 | 
					        .listRowSeparator(.hidden)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private func sessionRow(for session: SessionViewData) -> some View {
 | 
					    private func sessionRow(for session: SessionViewData, isRevoking: Bool = false) -> some View {
 | 
				
			||||||
        VStack(alignment: .leading, spacing: 10) {
 | 
					        VStack(alignment: .leading, spacing: 10) {
 | 
				
			||||||
            HStack(alignment: .top) {
 | 
					            HStack(alignment: .top) {
 | 
				
			||||||
                VStack(alignment: .leading, spacing: 6) {
 | 
					                VStack(alignment: .leading, spacing: 6) {
 | 
				
			||||||
@ -157,6 +188,9 @@ struct ActiveSessionsView: View {
 | 
				
			|||||||
                        .background(Color.accentColor.opacity(0.15))
 | 
					                        .background(Color.accentColor.opacity(0.15))
 | 
				
			||||||
                        .foregroundColor(.accentColor)
 | 
					                        .foregroundColor(.accentColor)
 | 
				
			||||||
                        .clipShape(Capsule())
 | 
					                        .clipShape(Capsule())
 | 
				
			||||||
 | 
					                } else if isRevoking {
 | 
				
			||||||
 | 
					                    ProgressView()
 | 
				
			||||||
 | 
					                        .progressViewStyle(.circular)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -225,6 +259,34 @@ struct ActiveSessionsView: View {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @MainActor
 | 
				
			||||||
 | 
					    private func revoke(session: SessionViewData) async {
 | 
				
			||||||
 | 
					        guard !session.isCurrent, !isRevoking(session: session) else {
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        revokingSessionIds.insert(session.id)
 | 
				
			||||||
 | 
					        defer { revokingSessionIds.remove(session.id) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					            let message = try await sessionsService.revoke(sessionId: session.id)
 | 
				
			||||||
 | 
					            sessions.removeAll { $0.id == session.id }
 | 
				
			||||||
 | 
					            activeAlert = SessionsAlert(
 | 
				
			||||||
 | 
					                title: NSLocalizedString("Готово", comment: "Заголовок успешного уведомления"),
 | 
				
			||||||
 | 
					                message: message
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        } catch {
 | 
				
			||||||
 | 
					            activeAlert = SessionsAlert(
 | 
				
			||||||
 | 
					                title: NSLocalizedString("Ошибка", comment: "Заголовок сообщения об ошибке"),
 | 
				
			||||||
 | 
					                message: error.localizedDescription
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private func isRevoking(session: SessionViewData) -> Bool {
 | 
				
			||||||
 | 
					        revokingSessionIds.contains(session.id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private var revokeOtherSessionsButton: some View {
 | 
					    private var revokeOtherSessionsButton: some View {
 | 
				
			||||||
        let primaryColor: Color = revokeInProgress ? .secondary : .red
 | 
					        let primaryColor: Color = revokeInProgress ? .secondary : .red
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user