Skip to content

Conversation

@mpivchev
Copy link
Collaborator

@mpivchev mpivchev commented Nov 26, 2025

Implements: #3793
Prerequisite:
nextcloud/NextcloudKit#204

image IMG_0607 IMG_0610

Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the user status functionality from UIKit to SwiftUI, splitting the combined user status and status message screen into two separate, focused screens. The refactor removes ~700 lines of UIKit code and replaces it with cleaner SwiftUI implementations while adding a 15-minute duration option to address a mobile-related bug.

Key Changes:

  • Complete removal of UIKit-based NCUserStatus.swift and storyboard, replacing with SwiftUI views (NCUserStatusView and NCStatusMessageView)
  • Separation of status selection (online/away/dnd/invisible/busy) from status message management (emoji + text message with expiration)
  • Addition of 15-minute clear duration option alongside existing options (30 min, 1 hr, 4 hrs, day, week)
  • Introduction of reusable EmojiTextField component for emoji-only input
  • Centralization of Xcode preview detection logic in NCGlobal.swift

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
iOSClient/UserStatus/NCUserStatus.swift Deleted 722-line UIKit implementation
iOSClient/UserStatus/NCUserStatus.storyboard Deleted corresponding storyboard file
iOSClient/UserStatus/NCUserStatusView.swift New SwiftUI view for selecting user status (online/away/dnd/invisible/busy)
iOSClient/UserStatus/NCUserStatusModel.swift New model managing user status state and API calls
iOSClient/StatusMessage/NCStatusMessageView.swift New SwiftUI view for setting status messages with emoji and expiration
iOSClient/StatusMessage/NCStatusMessageModel.swift New model managing status messages, including 15-minute option
iOSClient/StatusMessage/EmojiTextField.swift New reusable UIKit-backed emoji-only text field component
iOSClient/Utility/NCUtility+Image.swift Minor whitespace formatting improvements
iOSClient/NCGlobal.swift Added global isXcodeRunningForPreviews helper function
iOSClient/Extensions/View+Extension.swift Removed duplicate preview detection, now in NCGlobal
iOSClient/Transfers/NCTransfersModel.swift Updated to use centralized preview detection
iOSClient/Data/NCManageDatabase.swift Renamed previewCreateDB() to createDBForPreview() for consistency
Nextcloud.xcodeproj/project.pbxproj Updated project file with new source files and removed old ones

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

HStack(spacing: 12) {
EmojiField(text: $model.emojiText)

TextField("What is your status?", text: $model.statusText)
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded English string "What is your status?" should use a localization key wrapped with NSLocalizedString for proper internationalization support.

Suggested change
TextField("What is your status?", text: $model.statusText)
TextField(NSLocalizedString("What is your status?", comment: "Prompt for user to enter their status message"), text: $model.statusText)

Copilot uses AI. Check for mistakes.
Comment on lines 66 to 84
NextcloudKit.shared.getUserStatus(account: account) { task in
Task {
let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: self.account,
name: "getUserStatus")
await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task)
}
} completion: { account, clearAt, icon, message, messageId, messageIsPredefined, status, statusIsUserDefined, _, _, error in
if error == .success {
Task {
await NCManageDatabase.shared.setAccountUserStatusAsync(userStatusClearAt: clearAt,
userStatusIcon: icon,
userStatusMessage: message,
userStatusMessageId: messageId,
userStatusMessageIsPredefined: messageIsPredefined,
userStatusStatus: status,
userStatusStatusIsUserDefined: statusIsUserDefined,
account: account)
}
}
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method uses the callback-based getUserStatus API while other methods in the class use the async/await pattern with getUserStatusAsync. For consistency, consider refactoring to use getUserStatusAsync like in the getStatus method (line 38).

Suggested change
NextcloudKit.shared.getUserStatus(account: account) { task in
Task {
let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: self.account,
name: "getUserStatus")
await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task)
}
} completion: { account, clearAt, icon, message, messageId, messageIsPredefined, status, statusIsUserDefined, _, _, error in
if error == .success {
Task {
await NCManageDatabase.shared.setAccountUserStatusAsync(userStatusClearAt: clearAt,
userStatusIcon: icon,
userStatusMessage: message,
userStatusMessageId: messageId,
userStatusMessageIsPredefined: messageIsPredefined,
userStatusStatus: status,
userStatusStatusIsUserDefined: statusIsUserDefined,
account: account)
}
}
Task {
let status = await NextcloudKit.shared.getUserStatusAsync(account: account) { task in
Task {
let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: self.account,
name: "getUserStatus")
await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task)
}
}
// Assuming getUserStatusAsync returns a struct with the same fields as the callback
if status.error == .success {
await NCManageDatabase.shared.setAccountUserStatusAsync(
userStatusClearAt: status.clearAt,
userStatusIcon: status.icon,
userStatusMessage: status.message,
userStatusMessageId: status.messageId,
userStatusMessageIsPredefined: status.messageIsPredefined,
userStatusStatus: status.status,
userStatusStatusIsUserDefined: status.statusIsUserDefined,
account: account
)
}

Copilot uses AI. Check for mistakes.
Comment on lines 9 to 14
struct Status: Identifiable, Equatable {
let id = UUID()
let emoji: String
let title: String
let detail: String
}
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Status struct is defined but never used in the code. It appears to be leftover from development. Consider removing it to keep the codebase clean.

Suggested change
struct Status: Identifiable, Equatable {
let id = UUID()
let emoji: String
let title: String
let detail: String
}

Copilot uses AI. Check for mistakes.
let preset: NKUserStatus

var body: some View {
let cleatAtText = model.getPredefinedClearStatusString(clearAt: preset.clearAt, clearAtTime: preset.clearAtTime, clearAtType: preset.clearAtType)
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error: 'cleatAtText' should be 'clearAtText'

Copilot uses AI. Check for mistakes.
let cleatAtText = model.getPredefinedClearStatusString(clearAt: preset.clearAt, clearAtTime: preset.clearAtTime, clearAtType: preset.clearAtType)

Button(action: {
model.chooseStatusPreset(preset: preset, clearAtText: cleatAtText)
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error: 'cleatAtText' should be 'clearAtText' (same variable name used in line 105)

Copilot uses AI. Check for mistakes.
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
@mpivchev mpivchev merged commit 1260500 into master Nov 27, 2025
3 of 4 checks passed
@mpivchev mpivchev deleted the split-user branch November 27, 2025 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants