- Fix CI config
- Update Package.resolved format
- Since SwiftUI `List` is now implemented using collection view, tests that use `tables` are updated to use alternatives
- Generate additional screenshots for 6.7" display (iPhone 14 Pro Max) for App Store Connect
Currently, share plugin will load all the files been transferred into app's memory. This is problematic because iOS limits how much memory each app can use, so transferring large files will cause the app to run out of memory and crash. To make the matter worse, somehow bridging between `NSData` and `Data` caused Swift to make a copy of `NSData`'s contents, doubling the memory needed to transfer files.
This merge requests implements chunk based file transfer, where only a small portion of file contents is loaded into memory, while most remain on disk, for both sending and receiving. To simplify the logic, urls to payloads (i.e. file contents) are now stored in separate arrays for sending and receiving, so locking mechanism is simpler: use `_pendingLSockets` for locking shared resources for sending out files, and `_pendingRSockets` for receiving. Thus, it should also fix the "refresh discovery freezes app" issue that people have reported.
During the implementation process I've identified some potential issues to be fixed, but they remain TODOs to keep the diff/change in behavior more contained.
## Testing
The app's memory usage remained around 30MB before, during, and after the file transfer process. I was able to successfully receive large files such as Xcode.xip (around 7GB) with up to 20MiB/s transfer speed, receive multiple files transferred together, send a single/multiple file/photos/videos between KDE Connect iOS and KDE Connect Qt macOS client, and between iOS and iOS (with and without chunked file transfer)

Transfer speed dropped to around 10 MiB/s during when I tried to transfer another large file, but I suspect this is likely due to network condition instead of problem in the implementation. The following shows CPU, memory, disk, and network usage:

Fix crash on launch for running as iOS app on Mac
## Suggested Way of Testing
1. Install and run 0.3.0 (6) on Mac with Apple Silicon, it should crash on launch
2. Build, install, and run with changes in this MR, it should not crash on launch
On iOS 16, list selections in Split View now have a new default row background. This change updates the battery icon color to use the correct primary label color.
## Screenshots
### iOS 16
||Light (Fixed)|Dark (No change)|
|--|--|--|
|Old|||
|New|||
### iOS 15
No change
|Light|Dark|
|--|--|
|||
### iOS 14
**It has the same problem, but no change.** I was not able to find a solution.
|Light|Dark|
|--|--|
|||
Tested on iOS 14, 15 and 16 simulator; and iPhone running iOS 16.
## Reproduce
1. Go to "Configure Devices by IP"
2. Tap "+" button
3. Tap "return" key on the keyboard
4. Crash before this change, does not crash with this change.
https://github.com/robbiehanson/CocoaAsyncSocket/pull/802
This is a high impact bug that significantly increased our number of crashes. On iOS 16, the app crashes on refresh (or even launch sometimes), especially if another reachable/paired device is present.
Tested the fix on iPhone running iOS 16
## Changelog
- Lower test targets to iOS 14 (same as the main app)
- Separate Device initialization from network package
- Write UI test to take screenshots for most parts of the app
- Add fastlane as a dependency
- Force xcodebuild to use arm64 architecture when run by GitLab CI
## Usage
Install [fastlane](https://fastlane.tools/), navigate to KDE Connect folder in terminal, and run `fastlane screenshots`
## Motivation
As we are preparing for release on the App Store, one requirement is to provide screenshots. Automating the process (as much as we can) allows us to focus on other aspects of the development.
## Demo

```
+---------------------------------------+-------+
| snapshot results |
+---------------------------------------+-------+
| Device | en-US |
+---------------------------------------+-------+
| iPhone 8 Plus | 💚 |
| iPhone 13 Pro Max | 💚 |
| iPad Pro (12.9-inch) (2nd generation) | 💚 |
| iPad Pro (12.9-inch) (5th generation) | 💚 |
+---------------------------------------+-------+
[20:01:31]: Generating HTML Report
[20:01:31]: Successfully created HTML file with an overview of all the screenshots: '~/kdeconnect-ios/KDE Connect/fastlane/screenshots/screenshots.html'
+------+---------------------------------------------------------------+-------------+
| fastlane summary |
+------+---------------------------------------------------------------+-------------+
| Step | Action | Time (in s) |
+------+---------------------------------------------------------------+-------------+
| 1 | default_platform | 0 |
| 2 | if [ -z "`xcrun simctl list devices available | grep ' | 0 |
| 3 | capture_screenshots | 280 |
+------+---------------------------------------------------------------+-------------+
[20:01:33]: fastlane.tools finished successfully 🎉
```
## Changelog
- Added SwiftUI-Introspect as a dependency
- Replaced all `NSLog` and `print` with `OSLog`
- Added a hidden developer mode, activatable by:
- tapping the build version 10 consecutive times,
- activate the build version label with VoiceOver, or
- in `DEBUG` mode with `isDebugging` in the launch argument (enabled by default)
- Added a OSLog view to see the logs, with basic filters and search
- Added a Network Package composer to author network packages
- Added a hidden network package debug mode that sets capabilities to all network packges, activatable by:
- typing `isDebuggingNetworkPackage` in the Network Package composer payload text editor
- in `DEBUG` mode with `isDebuggingNetworkPackage` in the launch argument (disabled by default)
- Replace `[self]` with `[weak self]` everywhere
- Address crash on `Battery.sendBatteryStatusOut()`
- log Battery instance leak for debugging
## Note
- Debug messages are only available for viewing when attached to a debugger
- Privacy redaction is not applied to network packages (device's UUID assigned by KDE Connect and name will be exposed in the log)
- These logs are stored on users' devices only and we have no way of accessing them. Users must manually export/screenshot the logs
## Known Issues
- OSLog vieweing is only available on iOS 15 because Apple didn't have time to deliver it for iOS 14
- Network Package Composer does not support adding file payload because the existing payload mechanism consumes too much memory and is hard to work with
- Contributors need to learn OSLog: https://invent.kde.org/network/kdeconnect-ios/-/wikis/Logging-with-OSLog
## Demo


## Changelog
- Use the default navigation view style for all devices
- Move the device discovery help to the bottom toolbar (since footers might not always be displayed)
- Adjust layout of Settings view for accessibility font
- Choose better presenter view layout based on size class
Update README with information about App Store.
- Include link to App Store in TLDR
- Move TestFlight to a later section, and specify it supports iOS app on Mac with Apple silicon
## Changelog
- Enabled "Use Compiler to Extract Swift Strings" (`SWIFT_EMIT_LOC_STRINGS`) in build settings
- `Contributors.json` is replaced by `Contributors.swift` so it's easier for us to implement !67
- Internationalize `ColorScheme` (app theme) picking UI
- Added `NSLocalizedString` to parts of the program that's missing it
- Fixed typos and unified spellings
## Example XLIFF
[en.xliff](/uploads/896b985db5bd616fb0cf0c214f3933f2/en.xliff)
## Detours
I was initially misguided by [Preparing Views for Localization](https://developer.apple.com/documentation/swiftui/preparing-views-for-localization) saying that "Xcode doesn’t parse these views [other than Text] for localization, you need to manually add the localization strings." The code that switch all `LocalizedStringKey` to `Text` can be found at https://invent.kde.org/apollozhu/kdeconnect-ios/-/commits/work/localization/xcodebuild-exportLocalizations-backup, and it produced [en.xliff](/uploads/703d947032c6b2eb5f5b0b9352d2423e/en.xliff).
Fixing the error tone that sometimes happens after pairing succeeds.
## Reproduce Error Tone
### Setup
1. Pair devices
2. Verify that both can see the certificates' SHA256.
3. Quite the app
### Test
1. Saved Device
2. Unpair
3. Self or other pair
## Changelog
- Fixed app getting stuck on importing media when a large number of images/videos are selected
- Show detailed progress bar when loading images/videos
- Update text while loading images to "Preparing Media…" due to confusion about "Importing Media..." (since we should be sending those out)
- Load original HEIC images instead of jpg/png when possible
## Dependency Changes
- SwiftUI-MediaPicker 0.0.1 -> 0.2.0
- Pairing works fine with Ubuntu now, but there are quite a few reports about not working with Windows
- Someone suggested that we can implement clipboard sync through custom Siri Shortcuts and asked for URL Scheme
- We can't forward notifications, but it seems to be possible for other KDE Connect clients to retrieve iOS notifications https://invent.kde.org/network/kdeconnect-ios/-/wikis/Random-Notes#notification
- Emphasis that app can't work in the background:

At the moment `Backend.swift` gathers a number of different things that don't have much of a relation to each other.
This MR separates parts of `Backend.swift` into their own files.
Fixes crash caused by GSConnect implementation https://github.com/GSConnect/gnome-shell-extension-gsconnect/issues/1051
Justification: this "bug" has already been fixed by GSConnect, which now sends a String instead of JSON. However, this fix is to ensure that older version of GSConnect (which are quite common as they're version-freezes by Long-Term-Support distribution releases) don't cause crashes with KDE Connect iOS.
## Test
> Test case found in https://github.com/GSConnect/gnome-shell-extension-gsconnect/pull/1053
Check that a network package body like this always works:
```json
{
"commandList": "{\"command-uuid\":{\"name\": \"Test Command\",\"command\":\"ls\"}}"
}
```
Check that a network package body like this only works with this fix:
```json
{
"commandList": {
"command-uuid": {
"name": "Test Command",
"command": "ls"
}
}
}
```
Fixes saved devices not showing up until the `_devices` state changes again.
## Discussions
Have to include devicesListsMap in signature because the first invocation is before initialization is done
## Testing
Confirmed master is not working. Checked in the simulator with a previously paired device.
Finishing touch of !42, alerts queue.
## Changelog
- Fix crash on iOS 14 when finish editing
- Add auto focus empty ip address text field
- Add SwiftUI Introspect as dependency
- Add new folder for iOS 14 compatibility views
## Why was this not a part of Season of KDE
1. I wish I had more time to set this up, but we ran out of time
2. Implementation requires understanding of UIKit, Combine, property wrapper, and generics
Only consider payloadTransferInfo is for payload if with port specified.
## Bug Reports
- https://forum.kde.org/viewtopic.php?f=18&t=173218
- Various on TestFlight
- In KDE Connect group chat
## Testing
Tested to ensure that pairing and file transfer works with iOS, macOS, Android, and Ubuntu.
Per discussions in https://phabricator.kde.org/T15317, the app qualifies for exemption "**(c) Limited to authentication, digital signature**, or the decryption of data or files" provided in Category 5, Part 2 of the U.S. Export Administration Regulations. Thus, we add [ITSAppUsesNonExemptEncryption](https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption)
**Update, May 7th 2022:**
**Justification of exemption decision from the KDE Connect iOS developers:**
KDE Connect iOS uses encryption for the sole purpose of securing traffic between KDE Connect clients over the network and its related authentication. Therefore, it is reasonable to describe KDE Connect's usage of TLS encryption as a "message carrier" that carries the sole purpose of securing data during transfer, where it's not localized on the device on which the clients are installed onto.
To establish this secure transfer link, KDE Connect also uses encryption and digital signature to authenticate devices upon connection and pairing. This ensures that only devices that are authorized and trusted can be used to establish any secure connections for data transfer.
**Since KDE Connect's use of encryption lies solely for the purposes stated above, we (the KDE Connect developers) believe that all of the usage cases fall under the term "limited to authentication, digital signature, or the decryption of data or files" as defined by category (c) of the encryption. Therefore, we (the KDE Connect developers) believe that KDE Connect iOS is exempt from the App Store encryption compliance policies, with no additional actions required to release KDE Connect iOS on the App Store.**
Selecting the exempt option (as described above) in the App Store Connect portal effectively ends the encryption compliance process with the verdict that the app is not required to submit any further information regarding its use of encryption for the US regulations or French regulations. If our decision that KDE Connect iOS's qualification under exemption (c) is valid, no further actions would be needed in terms of encryption compliance to release the app on the App Store.
**Feature goal:** To implement a system that allows for queuing multiple alerts.
**Motivation:** Currently, if more than one alert were to appear on-screen, only the first one is displayed, the rest gets dismissed without showing them to the user.
Hi, this PR replaces the UIFeedbackImpactGenerator array in `Backend.swift` with an enum extension of FeedbackStyle. This should make calling the different levels of haptics more elegant and allows us to have to do fewer ugly rawValue conversions in the rest of the code
Hey all, found this task on Phabricator and took it, review welcome 😄
This PR replaces the previous constants with a single enum with a play method, per the suggestion in the comments of `Backend.swift`
## Changelog
Add a list of KDE Connect features and their implementation status in Settings.
## Rationale
There have been quite a few bug reports about the app not working in the background and questions about "is X available in KDE Connect iOS?" Having a features list allows us to:
1. be more transparent about what works what doesn't work, and hopefully reduce the number of questions about this
2. have a clear roadmap about what remains unimplemented and open for work
## Demo
|iOS 14|iOS 15|
|--|--|
|||
Seeking feedback about the new app icon design and feel free to let us know what you think!
## Suggested Feedback Template
1. How do you feel about the new logos?
2. Do the new logos better adhere to the [iOS Human Interface Design Guidelines](https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/app-icon/) than the old logo?
3. Are the new logos more recognizable as KDE Connect than the old logo, in general and when displayed among other apps?
4. In conclusion, would you suggest switching to one of the new logos? Why or why not?
5. If yes, should we provide the old/other logos as options for users to choose in-app?
6. Any other suggestions, questions, concerns, or things you'd like us to know?
---
## Rationale
1. Transparent, irregular-shaped icons don't work well on iOS; they will instead have a solid black background.
2. Icons are usually displayed with a small size, making the current one hard to distinguish from other apps. One TestFlight feedback suggests:
> UI/UX modification requests: 1. iOS devices use square icons with rounded corners. Current KDE connect logo on iPhone looks completely out of place, making it harder to recognize. Use the attached png logo instead. [image source: https://freesvg.org/kde-logo ] For ideal use - breeze grey color kde logo with white background if ios system theme is light and revese the colors if system is in dark mode.
## New Logos
The SVG versions are in the [Wiki](https://invent.kde.org/network/kdeconnect-ios/-/wikis/Logos) for future use.
||old|new|old on device|new on device|
|--|--|--|--|--|
|iOS (Android)|||||
|iOS (macOS)||[](https://dribbble.com/shots/17573735-KDE-Connect-iOS-App-Icon)|||
### iOS (Android)
0. This is the new default logo
1. Based on https://invent.kde.org/network/kdeconnect-android/-/merge_requests/279
2. The removal of gradient and higher contrast with orange background significantly improved the legibility
### iOS (macOS)
1. Preserves the device bezels (and most of the current design) to differentiate from KDE as a whole https://invent.kde.org/network/kdeconnect-android/-/merge_requests/119#note_22722
2. Having a non-vertical bezel hints that we not only support iPhones but also iPads (and Apple Silicon Macs)
3. Works with another new macOS icon candidate (not included in this MR) for when we make KDE Connect iOS serve as KDE Connect macOS in the future (note: not to replace the icon of the Qt version):
||old|new|old on device|new on device|
|--|--|--|--|--|
|macOS||[](https://dribbble.com/shots/17573418-KDE-Connect-macOS-11-App-Icon)|||
## UI Changes in App
|light mode|dark mode|
|--|--|
|||
## Demo

## References
- [iOS App Icon Guideline](https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/app-icon/)
- [macOS App Icon Guideline](https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/app-icon/)
- [Other macOS KDE icon designs](https://macosicons.com/#/kde)
Implements https://phabricator.kde.org/T15152
- `KeychainItemWrapper` is still in use, moved to `ObjC Backend`
- Deleted files from Unused and saved to https://invent.kde.org/network/kdeconnect-ios/-/snippets/2031 for future reference
- `SettingsListCellView` and `PlaceholderView` are not saved as they are easy to recreate
- Remove unused `import UIKit`, and import UIKit where they are used (where currently implicitly imported)
- This prepares us to have a better understanding of what needs to be done for enabling macOS target
**Context:** The "unused" folder was first introduced by @lucaswzx in July/August 2021 as a /tmp directory to house various files and code that were either removed from the active project during development, or housed temporarily for use later. At the time of this merge request, most of the files inside the directory are definitively unused in the project and likely wouldn't be included in any short-term future development plans.
## Changelog
- Removed TODOs & Plans from README since we are using Phabricator now
- Updated Lucas' website URL to the correct working one
- Lowered minimum iOS version to participate in TestFlight from 15 to 14
- Restructured README to have a clearer division between sections
- Misc wording and style changes
## Preview
https://invent.kde.org/apollozhu/kdeconnect-ios/-/tree/update-readme
No longer force unwrap the battery plugin that may not exist.
## Testing
- Tested to ensure the UI remains unchanged and auto-updates whenever changes happen
- Tested with no battery plugin added and the app no longer crashes
Change instructions to provide scenario-based help in DevicesView.
## Changelog
- Simplified the text displayed when each section is empty
- Adds a dedicated help popup for fixing device discovery issues
- Only include footer help for reconnecting previously connected devices if there are remembered devices
## Rationale
> **People look for help when they can’t figure out how to *accomplish a goal.*** Although users sometimes want a quick reference guide, they’re more likely to seek help with specific tasks. In general, describe control usage in the context of accomplishing a task.
> https://developer.apple.com/design/human-interface-guidelines/macos/user-interaction/help/#apple-help
We received a question about KDE Connect iOS not being able to discover other devices, and they were able to resolve it by following the instruction listed as the section footer, which is "Configure Devices by IP." Despite the current phrasing accurately identifying why the problem happened, it isn't clear to the users that the instruction is for such a problem.
Additionally, we have feedback on TestFlight that states:
> UI/UX modification requests: 4. Shorten the Discoverable Devices warning on the main opening page to this: "No new devices discovered. Please refresh discovery and check if other devices are running KDE connect & are on the same network as this this device." Current warning has some grammatical errors and lengthy text becomes distracting/confusing to user.
Thus, we could mimic examples from the iOS Settings App:
|Footer|Popover|
|--|--|
|||
|||
## Demo
### iOS 15
<details><summary>1. All sections are empty, no additional help other than for discovery</summary>

</details>
<details><summary>2. Has no remembered device</summary>

</details>
<details><summary>3. Has no discovered and no remembered device</summary>

</details>
<details><summary>4. Has remembered device, provides additional help about reconnecting remembered devices</summary>

</details>
<details><summary>5. Help for device discovery</summary>

</details>
#### iPad
<details><summary>Help for device discovery on iPad takes only readable width</summary>

</details>
## iOS 14 (difference only)
<details><summary>Footer is displayed as just another row</summary>

</details>
## Changelog
- Dangerous options are now in red on iOS 14
- Use `initWithData` instead of `stringWithUTF8String` for non-null terminated data to prevent memory access issues
- Reset navigation title to default behavior (use navigationTitle, removed the workaround to reduce top inset)
- **Rationale**: the workaround forced all Settings details views to use inline title because the hard-coded value is not working for those screens
## Screenshots
|iOS 14|iOS 15|
|--|--|
|||
In this merge request, we have implemented the about screen to show useful links, authors, and third-party libraries as well as an abstract view to display any ```NSAttributedString``` for compatibility with iOS 14.
As we do not sort deserialized arrays in code, future maintainers of ```contributors.json``` and ```libs.json``` should keep the order by ```name``` for ```contributors.json``` and ```id``` (project name) for ```libs.json```.
There are two places that can be improved by future development:
1. for function ```func getContributorListAttributedText(template: String, for category: KeyPath<Contributors, [Contributor]>) -> NSAttributedString```, the complexity of the current implementation is $`O(n^2)`$, and it might be optimized to $`O(n)`$
2. for section ```Actions```, we have tried ```LazyHGrid```, but it is not flexible enough for enlarged text (accessibility) and landscape orientation, so future development should take a look on how to implement a list similar to the Android app
Screenshots:


## Changelog
- Replaced `iOS14CompatibilityAlertView` with a more general `View+iOS14Compatibility.swift`
- Added modifiers mimicking SwiftUI 3 `alert` and `refreshable` to reduce code duplication
- Unfortunately, we don't have access to `SwiftUI.Button`'s internal workings, so we have to introduce `_Button`
- However, we can still use `Button` to construct either `SwiftUI.Button` or `_Button` depending on the arguments
## What happens when we drop iOS 14 support?
1. Delete `View+iOS14Compatibility.swift`
3. Done
## Testing
Manually tested on iOS 14.5 and iOS 15 simulators for all alerts.
## Known Issues
- Pull to refresh `refreshable` remains unimplemented for iOS 14
## Changelog
* Added SwiftUI-MediaPicker's pre-release 0.0.1 (up to next major) as a dependency
* Changed "Send files" to "Send Files" to be consistent with "Push Local Clipboard"
* Implemented sending images and videos from Photos Library
## Motivation
Currently, it's very inconvenient to send a photo saved in the Photos Library. Users expect to be able to directly select photos/videos from the Photos Library in-app without any additional steps (e.g. exporting to Files app and then selecting as a normal file). The Safari file selection dialog (which can be triggered using examples on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept) looks like:

## Approach
Integrate 3rd party dependency https://github.com/UWAppDev/SwiftUI-MediaPicker (which is under MIT License) through Swift Package Manager. ***Requires latest Xcode 13.2.1 release*** because it uses Swift Concurrency features and KDE Connect iOS supports iOS 14.
## Demo
