Skip to content

Add in-app camera with direct upload to Nextcloud#4058

Open
Rasmussw wants to merge 2 commits intonextcloud:masterfrom
Rasmussw:feature/direct-upload-camera-clean
Open

Add in-app camera with direct upload to Nextcloud#4058
Rasmussw wants to merge 2 commits intonextcloud:masterfrom
Rasmussw:feature/direct-upload-camera-clean

Conversation

@Rasmussw
Copy link
Copy Markdown

@Rasmussw Rasmussw commented Apr 8, 2026

This PR adds a custom in-app camera to the iOS client that captures photos and videos and uploads them directly to Nextcloud, bypassing the device camera roll by default. Users can optionally enable saving to the camera roll via a per-session toggle, with a global default available in Settings -> Advanced.

In the current flow, media is always saved to the system photo library before being uploaded to Nextcloud. This creates potentially unwanted local copies, introduces privacy concerns, and adds manual cleanup for users. This change ensures media can be captured and stored directly in Nextcloud without ever touching the camera roll. This is especially important in regulated environments with BYOD-policies, i.e. environments where media content captured can identify a person, thus potentially violating GDPR.

The custom camera uses AVFoundation to capture media directly to a temporary directory. Files are reviewed before upload and then passed into Nextcloud's existing upload pipeline. Saving to the camera roll is fully optional and only occurs if explicitly enabled by the user. Existing picker and upload flows remain unchanged.

Additional notes
Default behaviour does not affect existing users
Upload reliability uses existing background upload infrastructure
Camera roll is never accessed unless explicitly enabled

@marinofaggiana
Copy link
Copy Markdown
Member

@Rasmussw can you make a rebase ? thanks

Copy link
Copy Markdown
Member

@marinofaggiana marinofaggiana left a comment

Choose a reason for hiding this comment

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

Please make a rebase

@marinofaggiana marinofaggiana self-requested a review April 17, 2026 09:06
@Rasmussw Rasmussw force-pushed the feature/direct-upload-camera-clean branch from 7ded060 to 5b66fa5 Compare April 20, 2026 09:16
@Rasmussw
Copy link
Copy Markdown
Author

Hi @marinofaggiana I've rebased onto the latest master.

@marinofaggiana
Copy link
Copy Markdown
Member

Hi @marinofaggiana I've rebased onto the latest master.

There are some compilation errors (due to the master change). Please rebase and try compiling it. Thanks.

@Rasmussw Rasmussw force-pushed the feature/direct-upload-camera-clean branch from 5b66fa5 to 6efca7e Compare April 27, 2026 06:48
@marinofaggiana
Copy link
Copy Markdown
Member

Screenshot 2026-04-28 alle 09 26 17

Copy link
Copy Markdown
Member

@marinofaggiana marinofaggiana left a comment

Choose a reason for hiding this comment

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

do not build yet

@Rasmussw Rasmussw force-pushed the feature/direct-upload-camera-clean branch from 6efca7e to d375a16 Compare May 4, 2026 12:45
Introduces a custom AVFoundation camera that captures photos and videos
and uploads them directly to Nextcloud without saving to the device
camera roll by default.

- Custom camera UI: shutter, flash, flip, mode selector (photo/video)
- Pinch-to-zoom from 0.5x (ultra-wide) to 10x with live zoom label
- Virtual multi-camera support (triple/dual-wide) for sub-1x zoom
- Recording timer with red dot, screen stays on during video recording
- App backgrounding gracefully stops recording in progress
- Review screen after capture: retake or use, inline video playback
- "Save to camera roll" opt-in toggle per session (off by default)
- Global default for toggle in Settings -> Advanced
- Filenames follow Nextcloud conventions via createFileName(),
  including "Maintain original filename" mode (IMG_XXXX.JPG)
- Videos saved as .mov (QuickTime) matching Apple native camera format
- Restored live photo upload logic: livePhotoFile and nativeFormat
  were inadvertently removed in a previous refactor
- Fix: PHAuthorizationStatus.limited now correctly treated as authorized
- Fix: NCViewerQuickLookView crash when asset is nil after model change

Signed-off-by: Rasmus Wøldike <rswoldike@gmail.com>
@Rasmussw Rasmussw force-pushed the feature/direct-upload-camera-clean branch from d375a16 to 8330e77 Compare May 4, 2026 12:47
Signed-off-by: Rasmus Wøldike <rswoldike@gmail.com>
@Rasmussw Rasmussw force-pushed the feature/direct-upload-camera-clean branch from 8330e77 to 9b90f77 Compare May 4, 2026 12:54
@Rasmussw Rasmussw requested a review from marinofaggiana May 4, 2026 13:07
Copy link
Copy Markdown
Member

@marinofaggiana marinofaggiana left a comment

Choose a reason for hiding this comment

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

read first comments


var saveCameraMediaToCameraRoll: Bool {
get {
return getBoolPreference(key: "saveCameraMediaToCameraRoll", defaultValue: false)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

default, for compatibility with previous version, must be set to true

"_e2e_remove_folder_encrypted_" = "Decrypt";
"_e2e_file_encrypted_" = "File encrypted";
"_e2e_goto_settings_for_enable_" = "This is an encrypted directory, go to \"Settings\" and enable end-to-end encryption";
"_e2e_error_" = "An internal end-to-end encryption error occurred.";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

???

let isVideo: Bool
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it's used ?

@marinofaggiana
Copy link
Copy Markdown
Member

marinofaggiana commented May 5, 2026

iPad before:

IMG_0016

iPad after:

IMG_0017

In addition to the incorrect view incompatible with iPad, on the second attempt it did not display the image (black)

@marinofaggiana
Copy link
Copy Markdown
Member

Please use Lint, the code should be well formatted and commented in any modified places.

Screenshot 2026-05-05 alle 07 50 02

@marinofaggiana
Copy link
Copy Markdown
Member

Note: dear @Rasmussw It seems like the change is significant.
Why wasn't a fork on TLPhotoPicker considered to make the necessary changes there so as not to have to heavily intervene on the Nextcloud side of the process?

The library is very outdated and one might consider replacing it (also).

@Rasmussw
Copy link
Copy Markdown
Author

Rasmussw commented May 5, 2026 via email

@marinofaggiana
Copy link
Copy Markdown
Member

Hi @Rasmussw ,

Thanks for the clarification.

Yes, I am interested in this feature, and I think the proposed change is a very good improvement for the app.

From my point of view, keeping most of the implementation on the Nextcloud side is fine and probably easier to maintain. My main concern was the automatic save to the user’s Photo Library when taking a photo or video from TLPhotoPicker.

Since we have now identified the exact point where this happens, I think the cleanest solution would probably be a small and focused change in TLPhotoPicker: add a configuration flag to decide whether captured photos/videos should be saved to the Photo Library or written to a temporary/custom location instead.

On the Nextcloud side, we would then only need to retrieve those captured images/videos from that location and continue with the existing upload flow.

However, I also noticed that the camera capture UI/flow seems to have changed, especially on iPad. I would like to better understand that part before deciding the final direction, because this is not only about where the captured file is saved, but also about how the capture view is presented and handled across devices.

So, I would not require a full fork if this can be handled with a small, focused change. Ideally, this could be proposed upstream. If that is not possible, then a minimal fork limited to this behavior could also be acceptable.

We will of course also need to address the lint and iPad issues before merging.

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