├── README.md
├── .swiftlint-ci.yml
├── Sources
├── InfomaniakCoreSwiftUI
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── Files
│ │ │ ├── Contents.json
│ │ │ ├── Colors
│ │ │ ├── Contents.json
│ │ │ ├── file-audio-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-code-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-doc-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-font-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-grid-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-ics-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-img-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-pdf-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-point-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-vcard-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-video-color.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── file-archive-color.colorset
│ │ │ │ └── Contents.json
│ │ │ └── file-unknown-color.colorset
│ │ │ │ └── Contents.json
│ │ │ └── Images
│ │ │ ├── Contents.json
│ │ │ ├── file-audio.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-audio.svg
│ │ │ ├── file-code.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-code.svg
│ │ │ ├── file-doc.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-doc.svg
│ │ │ ├── file-font.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-font.svg
│ │ │ ├── file-grid.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-grid.svg
│ │ │ ├── file-ics.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-ics.svg
│ │ │ ├── file-img.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-image.svg
│ │ │ ├── file-pdf.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-pdf.svg
│ │ │ ├── file-point.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-point.svg
│ │ │ ├── file-vcard.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-vcard.svg
│ │ │ ├── file-video.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-video.svg
│ │ │ ├── file-archive.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-archive.svg
│ │ │ └── file-unknown.imageset
│ │ │ ├── Contents.json
│ │ │ └── file-unknown.svg
│ ├── Resources
│ │ ├── en.lproj
│ │ │ └── Localizable.strings
│ │ ├── de.lproj
│ │ │ └── Localizable.strings
│ │ ├── es.lproj
│ │ │ └── Localizable.strings
│ │ ├── fr.lproj
│ │ │ └── Localizable.strings
│ │ └── it.lproj
│ │ │ └── Localizable.strings
│ ├── Components
│ │ ├── Buttons
│ │ │ ├── Helpers
│ │ │ │ └── IKButtonConstants.swift
│ │ │ ├── Models
│ │ │ │ ├── IKButtonHeight.swift
│ │ │ │ └── IKButtonTheme.swift
│ │ │ ├── IKSquareButtonStyle.swift
│ │ │ └── ModalButtonsView.swift
│ │ ├── SafariWebView.swift
│ │ ├── AvatarView
│ │ │ ├── AvatarImage.swift
│ │ │ └── InitialsView.swift
│ │ ├── FloatingPanelCloseButton.swift
│ │ ├── ThemedLottieView.swift
│ │ ├── CameraPickerView.swift
│ │ ├── AlertView
│ │ │ └── AskForReviewView.swift
│ │ ├── Discovery
│ │ │ └── DiscoveryPresenter.swift
│ │ └── WebView.swift
│ ├── Helpers
│ │ ├── ReachabilityObserver.swift
│ │ └── FileType
│ │ │ ├── FileTypeProvider.swift
│ │ │ └── FileType.swift
│ ├── Extensions
│ │ ├── IKIconSize+Image.swift
│ │ └── IKPadding+View.swift
│ ├── Style
│ │ └── IKLabelStyle.swift
│ ├── MandatoryEnvironmentContainer.swift
│ ├── Modifiers
│ │ ├── CompactWindowDetectorModifier.swift
│ │ ├── SceneLifecycleModifier.swift
│ │ └── FloatingPanelHelper.swift
│ └── Alignment
│ │ └── IconAndMultilineTextAlignment.swift
├── InfomaniakPrivacyManagement
│ ├── Resources
│ │ ├── Assets.xcassets
│ │ │ ├── Contents.json
│ │ │ ├── chevron-right.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── chevron-right.svg
│ │ │ ├── matomo-short.imageset
│ │ │ │ └── Contents.json
│ │ │ ├── sentry-short.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── sentry.svg
│ │ │ │ └── sentry-dark.svg
│ │ │ ├── matomo-long.imageset
│ │ │ │ └── Contents.json
│ │ │ ├── sentry-long.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── sentry-text.svg
│ │ │ │ └── sentry-text-dark.svg
│ │ │ ├── backgroundColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── textPrimaryColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── textSecondaryColor.colorset
│ │ │ │ └── Contents.json
│ │ │ └── textTertiaryColor.colorset
│ │ │ │ └── Contents.json
│ │ └── Localizable
│ │ │ ├── en.lproj
│ │ │ └── Localizable.strings
│ │ │ ├── it.lproj
│ │ │ └── Localizable.strings
│ │ │ ├── fr.lproj
│ │ │ └── Localizable.strings
│ │ │ ├── es.lproj
│ │ │ └── Localizable.strings
│ │ │ └── de.lproj
│ │ │ └── Localizable.strings
│ ├── Extensions
│ │ └── MatomoUtils+Extension.swift
│ ├── PrivacyManagementCell.swift
│ ├── Tracker.swift
│ └── TrackerDetailsView.swift
├── InfomaniakCoreCommonUI
│ ├── Assets.xcassets
│ │ ├── InfomaniakColors
│ │ │ ├── Contents.json
│ │ │ ├── cobaltColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── coralColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── grassColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── jeanColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── mauveColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── princeColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── yellowColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── fougereColor.colorset
│ │ │ │ └── Contents.json
│ │ │ └── tropicalColor.colorset
│ │ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── infomaniakColor.colorset
│ │ │ └── Contents.json
│ │ ├── backgroundCardView.colorset
│ │ │ └── Contents.json
│ │ ├── primaryTextColor.colorset
│ │ │ └── Contents.json
│ │ ├── backgroundCardViewSelected.colorset
│ │ │ └── Contents.json
│ │ └── titleColor.colorset
│ │ │ └── Contents.json
│ ├── Extensions
│ │ ├── OSLog+Extension.swift
│ │ └── UIApplication+Extension.swift
│ ├── SnackBar
│ │ ├── IKRootViewController.swift
│ │ ├── IKWrapperView.swift
│ │ ├── IKSnackBarAvoider.swift
│ │ ├── IKSnackBarPresentable.swift
│ │ └── IKWindow.swift
│ ├── UIView+Extension.swift
│ ├── Utils
│ │ └── OrientationManager.swift
│ ├── Assets
│ │ └── Assets+InfomaniakCore.swift
│ ├── AvatarColors.swift
│ └── Security
│ │ └── AppLockHelper.swift
├── InfomaniakCoreUIResources
│ ├── swiftgen.yml
│ └── Localizable
│ │ ├── en.lproj
│ │ └── Localizable.strings
│ │ ├── es.lproj
│ │ └── Localizable.strings
│ │ ├── it.lproj
│ │ └── Localizable.strings
│ │ ├── de.lproj
│ │ └── Localizable.strings
│ │ └── fr.lproj
│ │ └── Localizable.strings
├── DesignSystem
│ ├── DesignTokens
│ │ ├── IKIconSize.swift
│ │ ├── IKRadius.swift
│ │ └── IKPadding.swift
│ └── Extensions
│ │ ├── Color+Extension.swift
│ │ └── Font+Extension.swift
└── InfomaniakCoreUIKit
│ ├── UITableView
│ └── UITableView+Extension.swift
│ ├── Extension
│ ├── UIColor+Extension.swift
│ ├── Model
│ │ ├── OrganisationAccount+Color.swift
│ │ └── InfomaniakUser+Avatar.swift
│ ├── UIViewController+Extension.swift
│ └── UIView+Extension.swift
│ ├── UIButton
│ └── UIButton+Extension.swift
│ ├── UILabel
│ └── IKLabel.swift
│ ├── UICollectionView
│ └── InsetCollectionViewCell.swift
│ └── TitleSizeAdjustingNavigationController.swift
├── .mise.toml
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── .github
├── workflows
│ ├── auto-author-assign.yml
│ ├── swiftformat.yml
│ ├── swiftlint.yml
│ ├── dependent-issues.yml
│ ├── ci.yml
│ └── semantic-commit.yml
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── .sonarcloud.properties
├── file-header-template.txt
├── Tests
└── InfomaniakCoreUITests
│ └── InfomaniakCoreUITests.swift
├── .gitignore
├── .swiftlint.yml
├── .swiftformat
└── Package.swift
/README.md:
--------------------------------------------------------------------------------
1 | # ios-core-ui
2 | UI component collection
3 |
--------------------------------------------------------------------------------
/.swiftlint-ci.yml:
--------------------------------------------------------------------------------
1 | disabled_rules:
2 | - todo
3 | strict: true
4 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.mise.toml:
--------------------------------------------------------------------------------
1 | [tools]
2 | swiftformat = '0.54.5'
3 | swiftlint = '0.57.0'
4 | swiftgen = "latest"
5 | pipx = "latest"
6 | "pipx:infomaniak/importloco" = "1.1.0"
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/InfomaniakColors/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "properties" : {
7 | "provides-namespace" : true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "properties" : {
7 | "generate-swift-asset-symbol-extensions" : "enabled"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Resources/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | InfomaniakCoreUI
4 |
5 | Created by Ambroise Decouttere on 15/10/2024.
6 |
7 | */
8 |
9 | /* Close button */
10 | "Close" = "Close";
11 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Resources/de.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | InfomaniakCoreUI
4 |
5 | Created by Ambroise Decouttere on 15/10/2024.
6 |
7 | */
8 |
9 | /* Close button */
10 | "Close" = "Schliessen";
11 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Resources/es.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | InfomaniakCoreUI
4 |
5 | Created by Ambroise Decouttere on 15/10/2024.
6 |
7 | */
8 |
9 | /* Close button */
10 | "Close" = "Cerrar";
11 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Resources/fr.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | InfomaniakCoreUI
4 |
5 | Created by Ambroise Decouttere on 15/10/2024.
6 |
7 | */
8 |
9 | /* Close button */
10 | "Close" = "Fermer";
11 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Resources/it.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | InfomaniakCoreUI
4 |
5 | Created by Ambroise Decouttere on 15/10/2024.
6 |
7 | */
8 |
9 | /* Close button */
10 | "Close" = "Chiudere";
11 |
--------------------------------------------------------------------------------
/.github/workflows/auto-author-assign.yml:
--------------------------------------------------------------------------------
1 | name: Auto Author Assign
2 |
3 | on:
4 | pull_request_target:
5 | types: [ opened, reopened ]
6 |
7 | permissions:
8 | pull-requests: write
9 |
10 | jobs:
11 | assign-author:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: toshimaru/auto-author-assign@v1.6.2
15 |
--------------------------------------------------------------------------------
/.sonarcloud.properties:
--------------------------------------------------------------------------------
1 | ## Path to sources
2 | sonar.sources=Sources
3 | # sonar.exclusions=
4 | # sonar.inclusions=
5 |
6 | ## Path to tests
7 | sonar.tests=Tests
8 | # sonar.test.exclusions=
9 | # sonar.test.inclusions=
10 |
11 | ## Source encoding
12 | # sonar.sourceEncoding=
13 |
14 | # Exclusions for copy-paste detection
15 | # sonar.cpd.exclusions=
16 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-audio.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-audio.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-code.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-code.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-doc.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-doc.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-font.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-font.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-grid.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-grid.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-ics.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-ics.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-img.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-image.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-pdf.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-pdf.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-point.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-point.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-vcard.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-vcard.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-video.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-video.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-archive.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-archive.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-unknown.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "file-unknown.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/chevron-right.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "chevron-right.svg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true,
14 | "template-rendering-intent" : "template"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-unknown.imageset/file-unknown.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/infomaniakColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "1.000",
9 | "green" : "0.596",
10 | "red" : "0.000"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/matomo-short.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "matomo.svg",
5 | "idiom" : "universal"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "filename" : "matomo-dark.svg",
15 | "idiom" : "universal"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "preserves-vector-representation" : true
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/sentry-short.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "sentry.svg",
5 | "idiom" : "universal"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "filename" : "sentry-dark.svg",
15 | "idiom" : "universal"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "preserves-vector-representation" : true
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/matomo-long.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "matomo-text.svg",
5 | "idiom" : "universal"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "filename" : "matomo-text-dark.svg",
15 | "idiom" : "universal"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "preserves-vector-representation" : true
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/sentry-long.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "sentry-text.svg",
5 | "idiom" : "universal"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "filename" : "sentry-text-dark.svg",
15 | "idiom" : "universal"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "preserves-vector-representation" : true
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-ics.imageset/file-ics.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/workflows/swiftformat.yml:
--------------------------------------------------------------------------------
1 | name: SwiftFormat
2 |
3 | on:
4 | pull_request:
5 | branches: [ main ]
6 |
7 | jobs:
8 | build:
9 | name: SwiftFormat
10 | runs-on: [ self-hosted, iOS ]
11 |
12 | steps:
13 | - name: Cancel Previous Runs
14 | uses: styfle/cancel-workflow-action@0.12.1
15 | with:
16 | access_token: ${{ github.token }}
17 | - uses: jdx/mise-action@v2
18 | with:
19 | cache: false
20 | - name: Checkout
21 | uses: actions/checkout@v4
22 | with:
23 | fetch-depth: 0
24 | - name: SwiftFormat
25 | run: swiftformat --lint . --reporter github-actions-log
26 |
--------------------------------------------------------------------------------
/.github/workflows/swiftlint.yml:
--------------------------------------------------------------------------------
1 | name: SwiftLint
2 |
3 | on:
4 | pull_request:
5 | branches: [ main ]
6 |
7 | jobs:
8 | build:
9 | name: SwiftLint
10 | runs-on: [ self-hosted, iOS ]
11 |
12 | steps:
13 | - name: Cancel Previous Runs
14 | uses: styfle/cancel-workflow-action@0.12.1
15 | with:
16 | access_token: ${{ github.token }}
17 | - uses: jdx/mise-action@v2
18 | with:
19 | cache: false
20 | - name: Checkout
21 | uses: actions/checkout@v4
22 | with:
23 | fetch-depth: 0
24 | - name: SwiftLint
25 | run: swiftlint --config .swiftlint.yml --config .swiftlint-ci.yml --reporter github-actions-logging .
26 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-font.imageset/file-font.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/workflows/dependent-issues.yml:
--------------------------------------------------------------------------------
1 | name: Dependent Issues
2 |
3 | on:
4 | issues:
5 | types:
6 | - opened
7 | - edited
8 | - closed
9 | - reopened
10 | pull_request_target:
11 | types:
12 | - opened
13 | - edited
14 | - closed
15 | - reopened
16 | # Makes sure we always add status check for PRs. Useful only if
17 | # this action is required to pass before merging. Otherwise, it
18 | # can be removed.
19 | - synchronize
20 |
21 | jobs:
22 | check:
23 | runs-on: ubuntu-latest
24 | steps:
25 | - uses: z0al/dependent-issues@v1
26 | env:
27 | # (Required) The token to use to make API calls to GitHub.
28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-vcard.imageset/file-vcard.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI workflow
2 |
3 | on:
4 | pull_request:
5 | branches: [ main ]
6 |
7 | jobs:
8 | build_and_test_iOS:
9 | name: Build and Test project on iOS
10 | runs-on: [ self-hosted, iOS ]
11 |
12 | steps:
13 | - name: Cancel Previous Runs
14 | uses: styfle/cancel-workflow-action@0.12.1
15 | with:
16 | access_token: ${{ github.token }}
17 | - name: Checkout
18 | uses: actions/checkout@v4
19 | - name: Build
20 | run: xcodebuild -scheme InfomaniakCoreUI-Package build -sdk iphonesimulator -destination "generic/platform=iOS"
21 | - name: Test
22 | run: xcodebuild -scheme InfomaniakCoreUI-Package test -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 17,OS=latest"
23 |
--------------------------------------------------------------------------------
/file-header-template.txt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | Infomaniak Core UI - iOS
4 | Copyright (C) 2023 Infomaniak Network SA
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-video.imageset/file-video.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/workflows/semantic-commit.yml:
--------------------------------------------------------------------------------
1 | name: 'PR and Commit Message Check'
2 | on:
3 | pull_request_target:
4 | types:
5 | - opened
6 | - edited
7 | - reopened
8 | - synchronize
9 |
10 | jobs:
11 | check-commit-message:
12 | name: Check Commit Message
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Check Commit Message
16 | uses: gsactions/commit-message-checker@v2
17 | with:
18 | pattern: '^(Merge .+|((feat|fix|chore|docs|style|refactor|perf|ci|test)(\(.+\))?: [A-Z0-9].+[^.\s])$)'
19 | error: 'Commit messages and PR title should match conventional commit convention and start with an uppercase.'
20 | excludeDescription: 'true'
21 | excludeTitle: 'false'
22 | checkAllCommitMessages: 'true'
23 | accessToken: ${{ secrets.GITHUB_TOKEN }}
24 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-grid.imageset/file-grid.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/chevron-right.imageset/chevron-right.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-doc.imageset/file-doc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 |
12 |
13 | **Is your feature request related to a problem? Please describe.**
14 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
15 |
16 | **Describe the solution you'd like**
17 | A clear and concise description of what you want to happen.
18 |
19 | **Describe alternatives you've considered**
20 | A clear and concise description of any alternative solutions or features you've considered.
21 |
22 | **Additional context**
23 | Add any other context or screenshots about the feature request here.
24 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/backgroundCardView.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "1.000",
9 | "green" : "1.000",
10 | "red" : "1.000"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0x2F",
27 | "green" : "0x2E",
28 | "red" : "0x2D"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/primaryTextColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.400",
9 | "green" : "0.400",
10 | "red" : "0.400"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0.620",
27 | "green" : "0.620",
28 | "red" : "0.620"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/InfomaniakColors/cobaltColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xB2",
9 | "green" : "0x6A",
10 | "red" : "0x00"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xF5",
27 | "green" : "0xB2",
28 | "red" : "0x0A"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/InfomaniakColors/coralColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x0B",
9 | "green" : "0x54",
10 | "red" : "0xFF"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0x59",
27 | "green" : "0x94",
28 | "red" : "0xFD"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/InfomaniakColors/grassColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x50",
9 | "green" : "0xAF",
10 | "red" : "0x4B"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0x93",
27 | "green" : "0xD0",
28 | "red" : "0x90"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/InfomaniakColors/jeanColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xF3",
9 | "green" : "0x96",
10 | "red" : "0x21"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xF8",
27 | "green" : "0xC4",
28 | "red" : "0x81"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/InfomaniakColors/mauveColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xC8",
9 | "green" : "0x68",
10 | "red" : "0xBA"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xD6",
27 | "green" : "0x8F",
28 | "red" : "0xCC"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/InfomaniakColors/princeColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xB7",
9 | "green" : "0x3A",
10 | "red" : "0x67"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xDD",
27 | "green" : "0x6D",
28 | "red" : "0x95"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/InfomaniakColors/yellowColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x0A",
9 | "green" : "0xC1",
10 | "red" : "0xFF"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0x9E",
27 | "green" : "0xDF",
28 | "red" : "0xFF"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-audio-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xD4",
9 | "green" : "0xBC",
10 | "red" : "0x00"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "234",
27 | "green" : "222",
28 | "red" : "134"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-code-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xB7",
9 | "green" : "0x3A",
10 | "red" : "0x67"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xDD",
27 | "green" : "0x6D",
28 | "red" : "0x95"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-doc-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xF3",
9 | "green" : "0x96",
10 | "red" : "0x21"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xF8",
27 | "green" : "0xC4",
28 | "red" : "0x81"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-font-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xB0",
9 | "green" : "0x26",
10 | "red" : "0x9C"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xDE",
27 | "green" : "0x68",
28 | "red" : "0xCD"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-grid-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x50",
9 | "green" : "0xAF",
10 | "red" : "0x4B"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0x93",
27 | "green" : "0xD0",
28 | "red" : "0x90"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-ics-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xEB",
9 | "green" : "0xD0",
10 | "red" : "0x36"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xF6",
27 | "green" : "0xE9",
28 | "red" : "0xA2"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-img-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xD4",
9 | "green" : "0xBC",
10 | "red" : "0x00"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xEA",
27 | "green" : "0xDE",
28 | "red" : "0x86"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-pdf-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x0B",
9 | "green" : "0x54",
10 | "red" : "0xFF"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0x59",
27 | "green" : "0x94",
28 | "red" : "0xFD"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-point-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x02",
9 | "green" : "0x98",
10 | "red" : "0xFF"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0x66",
27 | "green" : "0xC1",
28 | "red" : "0xFF"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-vcard-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xE1",
9 | "green" : "0x66",
10 | "red" : "0x9D"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xEE",
27 | "green" : "0xAA",
28 | "red" : "0xC8"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-video-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xD4",
9 | "green" : "0xBC",
10 | "red" : "0x00"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xEA",
27 | "green" : "0xDE",
28 | "red" : "0x86"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/InfomaniakColors/fougereColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x88",
9 | "green" : "0x96",
10 | "red" : "0x00"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xB3",
27 | "green" : "0xC7",
28 | "red" : "0x00"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/InfomaniakColors/tropicalColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xD4",
9 | "green" : "0xBC",
10 | "red" : "0x00"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xEA",
27 | "green" : "0xDE",
28 | "red" : "0x86"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/backgroundCardViewSelected.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.816",
9 | "green" : "0.792",
10 | "red" : "0.792"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0.816",
27 | "green" : "0.796",
28 | "red" : "0.796"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-archive-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x8B",
9 | "green" : "0x7D",
10 | "red" : "0x60"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xC0",
27 | "green" : "0xB7",
28 | "red" : "0xA5"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Colors/file-unknown-color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xB6",
9 | "green" : "0xA2",
10 | "red" : "0x85"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xCF",
27 | "green" : "0xC2",
28 | "red" : "0xAF"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/backgroundColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0xFF",
9 | "green" : "0xFF",
10 | "red" : "0xFF"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0x10",
27 | "green" : "0x10",
28 | "red" : "0x10"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/textPrimaryColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x33",
9 | "green" : "0x33",
10 | "red" : "0x33"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0xF1",
27 | "green" : "0xF1",
28 | "red" : "0xF1"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/textSecondaryColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x66",
9 | "green" : "0x66",
10 | "red" : "0x66"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0x9F",
27 | "green" : "0x9F",
28 | "red" : "0x9F"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/textTertiaryColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x9F",
9 | "green" : "0x9F",
10 | "red" : "0x9F"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0x66",
27 | "green" : "0x66",
28 | "red" : "0x66"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/Buttons/Helpers/IKButtonConstants.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2024 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import Foundation
20 |
21 | public enum IKButtonConstants {
22 | public static let maxWidth: CGFloat = 500
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets.xcassets/titleColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.200",
9 | "green" : "0.200",
10 | "red" : "0.200"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "1.000",
27 | "green" : "1.000",
28 | "red" : "1.000"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | },
38 | "properties" : {
39 | "localizable" : true
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-audio.imageset/file-audio.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Extensions/OSLog+Extension.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import OSLog
20 |
21 | public extension Logger {
22 | private static var subsystem = "InfomaniakCoreUI"
23 |
24 | static let view = Logger(subsystem: subsystem, category: "view")
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-img.imageset/file-image.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Extensions/MatomoUtils+Extension.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import Foundation
20 | import InfomaniakCoreCommonUI
21 |
22 | public protocol MatomoOptOutable {
23 | func optOut(_ optOut: Bool)
24 | }
25 |
26 | extension MatomoUtils: MatomoOptOutable {}
27 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/SnackBar/IKRootViewController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #if canImport(UIKit)
20 |
21 | import UIKit
22 |
23 | final class IKRootViewController: UIViewController {
24 | override func loadView() {
25 | view = IKWrapperView()
26 | }
27 | }
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 |
12 |
13 | **Description**
14 | A clear and concise description of what the bug is.
15 |
16 | **Steps to reproduce**
17 | Steps to reproduce the behavior:
18 | 1. Go to '...'
19 | 2. Click on '....'
20 | 3. Scroll down to '....'
21 | 4. See error
22 |
23 | **Expected behavior**
24 | A clear and concise description of what you expected to happen.
25 |
26 | **Screenshots**
27 | If applicable, add screenshots to help explain your problem.
28 |
29 | **Smartphone (please complete the following information):**
30 | - Device: [e.g. iPhone 12]
31 | - iOS version: [e.g. iOS 14.0]
32 | - App version: [e.g. 4.0.1]
33 |
34 | **Additional context**
35 | Add any other context about the problem here.
36 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-point.imageset/file-point.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIResources/swiftgen.yml:
--------------------------------------------------------------------------------
1 | # Infomaniak Core UI - iOS
2 | # Copyright (C) 2025 Infomaniak Network SA
3 | #
4 | # This program is free software: you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation, either version 3 of the License, or
7 | # (at your option) any later version.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License
15 | # along with this program. If not, see .
16 |
17 | output_dir: Generated/
18 |
19 | strings:
20 | inputs: Localizable/en.lproj
21 | outputs:
22 | - templateName: structured-swift5
23 | output: Strings+Generated.swift
24 | params:
25 | enumName: CoreUILocalizable
26 | publicAccess: true
27 |
--------------------------------------------------------------------------------
/Sources/DesignSystem/DesignTokens/IKIconSize.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import Foundation
20 |
21 | /// An enumeration to list the size of icons used for Infomaniak apps.
22 | @frozen public enum IKIconSize: CGFloat {
23 | /// 12pt icon
24 | case small = 12
25 | /// 16pt icon
26 | case medium = 16
27 | /// 24pt icon
28 | case large = 24
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/DesignSystem/DesignTokens/IKRadius.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import Foundation
20 |
21 | /// An enumeration to list the cornier radii used for Infomaniak apps.
22 | @frozen public enum IKRadius {
23 | /// 4pt radius
24 | public static let small: CGFloat = 4
25 | /// 8pt radius
26 | public static let medium: CGFloat = 8
27 | /// 16pt radius
28 | public static let large: CGFloat = 16
29 | }
30 |
--------------------------------------------------------------------------------
/Tests/InfomaniakCoreUITests/InfomaniakCoreUITests.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import InfomaniakCore
20 | import InfomaniakCoreCommonUI
21 | import InfomaniakCoreUIKit
22 | import XCTest
23 |
24 | final class InfomaniakCoreUITests: XCTestCase {
25 | func testCanInit_IKLabel() throws {
26 | // GIVEN
27 | let label = IKLabel()
28 |
29 | // THEN
30 | XCTAssertNotNil(label)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/SnackBar/IKWrapperView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Mail - iOS App
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #if canImport(UIKit)
20 |
21 | import UIKit
22 |
23 | final class IKWrapperView: UIView {
24 | override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
25 | let view = super.hitTest(point, with: event)
26 | if view != self {
27 | return view
28 | }
29 | return nil
30 | }
31 | }
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-archive.imageset/file-archive.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/SnackBar/IKSnackBarAvoider.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Mail - iOS App
3 | Copyright (C) 2022 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #if canImport(UIKit)
20 |
21 | import UIKit
22 |
23 | public final class IKSnackBarAvoider {
24 | public var snackBarInset: CGFloat = 0
25 |
26 | public init() { /* Needed to init */ }
27 |
28 | public func addAvoider(inset: CGFloat) {
29 | if inset != snackBarInset {
30 | snackBarInset = inset
31 | }
32 | }
33 |
34 | public func removeAvoider() {
35 | snackBarInset = 0
36 | }
37 | }
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/UIView+Extension.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import UIKit
20 |
21 | public extension UIView {
22 | func addShadow(elevation: Double = 1) {
23 | layer.shadowColor = UIColor.black.cgColor
24 | layer.shadowOffset = CGSize(width: 0.0, height: 1.23118 * elevation - 0.03933)
25 | layer.shadowOpacity = 0.17
26 | layer.shadowRadius = CGFloat(0.666920 * elevation - 0.001648)
27 | layer.shouldRasterize = true
28 | layer.rasterizationScale = UIScreen.main.scale
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Helpers/ReachabilityObserver.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2024 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import InfomaniakCore
20 | import SwiftUI
21 |
22 | @MainActor
23 | public final class ReachabilityObserver: ObservableObject {
24 | @Published public var networkStatus = ReachabilityListener.instance.currentStatus
25 |
26 | public init() {
27 | ReachabilityListener.instance.observeNetworkChange(self) { [weak self] status in
28 | Task { @MainActor in
29 | self?.networkStatus = status
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/SafariWebView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SafariServices
20 | import SwiftUI
21 |
22 | public struct SafariWebView: UIViewControllerRepresentable {
23 | let url: URL
24 |
25 | public init(url: URL) {
26 | self.url = url
27 | }
28 |
29 | public func makeUIViewController(context: Context) -> SFSafariViewController {
30 | return SFSafariViewController(url: url)
31 | }
32 |
33 | public func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {}
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/Buttons/Models/IKButtonHeight.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 |
21 | @available(iOS 15.0, *)
22 | public enum IKButtonHeight {
23 | public static let extraLarge: CGFloat = 64
24 | public static let large: CGFloat = 56
25 | public static let medium: CGFloat = 40
26 |
27 | static func convert(controlSize: ControlSize) -> CGFloat {
28 | if controlSize == .large {
29 | return IKButtonHeight.large
30 | } else {
31 | return IKButtonHeight.medium
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Extensions/IKIconSize+Image.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import DesignSystem
20 | import SwiftUI
21 |
22 | public extension Image {
23 | /// Resizes and scales the image to the specified ``IKIconSize`` size.
24 | /// - Parameter size: The specified size.
25 | /// - Returns: A square view containing the image scaled to fit in a frame of the specified size.
26 | func iconSize(_ size: IKIconSize) -> some View {
27 | resizable()
28 | .scaledToFit()
29 | .frame(width: size.rawValue, height: size.rawValue)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIKit/UITableView/UITableView+Extension.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import UIKit
20 |
21 | public extension UITableView {
22 | func register(cellView: AnyClass) {
23 | let name = String(describing: cellView.self)
24 | register(UINib(nibName: name, bundle: nil), forCellReuseIdentifier: name)
25 | }
26 |
27 | func dequeueReusableCell(type: CellClass.Type, for indexPath: IndexPath) -> CellClass {
28 | return dequeueReusableCell(withIdentifier: String(describing: type.self), for: indexPath) as! CellClass
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/DesignSystem/Extensions/Color+Extension.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 |
21 | #if os(macOS)
22 | public typealias PlatformColor = NSColor
23 | #elseif os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
24 | public typealias PlatformColor = UIColor
25 | #endif
26 |
27 | public extension PlatformColor {
28 | convenience init(light: PlatformColor, dark: PlatformColor) {
29 | self.init { $0.userInterfaceStyle == .dark ? dark : light }
30 | }
31 | }
32 |
33 | public extension Color {
34 | init(light: PlatformColor, dark: PlatformColor) {
35 | self.init(uiColor: UIColor(light: light, dark: dark))
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Extensions/UIApplication+Extension.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import UIKit
20 |
21 | public extension UIApplication {
22 | var mainSceneKeyWindow: UIWindow? {
23 | // We want to have at least one foreground scene but we prefer active scenes rather than inactive ones
24 | let foregroundScenes = Array(connectedScenes).filter { $0.activationState == .foregroundActive }
25 | + Array(connectedScenes).filter { $0.activationState == .foregroundInactive }
26 | return foregroundScenes
27 | .compactMap { $0 as? UIWindowScene }
28 | .flatMap(\.windows)
29 | .first(where: \.isKeyWindow)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-code.imageset/file-code.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Extensions/IKPadding+View.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import DesignSystem
20 | import SwiftUI
21 |
22 | public extension View {
23 | /// Adds the padding amount specified by ``IKPadding`` to specific edges
24 | /// of this view.
25 | ///
26 | /// - Parameters:
27 | /// - edges: The set of edges to pad for this view. The default
28 | /// is `Edge.Set = .all`.
29 | /// - value: The amount of padding described by the ``IKPadding``
30 | /// struct.
31 | ///
32 | /// - Returns: A view that's padded by the specified amount on the specified edges.
33 | @inlinable func padding(_ edges: Edge.Set = .all, value: IKPadding.Option) -> some View {
34 | padding(edges, value.rawValue)
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Style/IKLabelStyle.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2024 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import DesignSystem
20 | import SwiftUI
21 |
22 | @available(iOS 15.0, *)
23 | public struct IKLabelStyle: LabelStyle {
24 | var spacing = IKPadding.mini
25 |
26 | public func makeBody(configuration: Configuration) -> some View {
27 | HStack(spacing: spacing) {
28 | configuration.icon
29 | configuration.title
30 | }
31 | }
32 | }
33 |
34 | @available(iOS 15.0, *)
35 | public extension LabelStyle where Self == IKLabelStyle {
36 | static var ikLabel: IKLabelStyle {
37 | return IKLabelStyle()
38 | }
39 |
40 | static func ikLabel(_ spacing: CGFloat) -> IKLabelStyle {
41 | return IKLabelStyle(spacing: spacing)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/AvatarView/AvatarImage.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 |
21 | public struct AvatarImage: View {
22 | let image: Image
23 | let size: CGFloat
24 |
25 | public init(image: Image, size: CGFloat) {
26 | self.image = image
27 | self.size = size
28 | }
29 |
30 | public var body: some View {
31 | ZStack {
32 | Circle()
33 | .fill(.white)
34 |
35 | image
36 | .resizable()
37 | .scaledToFit()
38 | .clipShape(Circle())
39 | }
40 | .frame(width: size, height: size)
41 | .drawingGroup()
42 | }
43 | }
44 |
45 | #Preview {
46 | AvatarImage(image: Image(systemName: "person"), size: 40)
47 | }
48 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/MandatoryEnvironmentContainer.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2024 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import Foundation
20 |
21 | public struct MandatoryEnvironmentContainer: Equatable where T: Equatable {
22 | public var value: T {
23 | #if DEBUG
24 | guard let _value else {
25 | fatalError("Container not initialized in the view tree")
26 | }
27 | return _value
28 | #else
29 | return _value!
30 | #endif
31 | }
32 |
33 | private let _value: T?
34 |
35 | public init(value: T) {
36 | _value = value
37 | }
38 |
39 | private init(value: T?) {
40 | _value = value
41 | }
42 |
43 | public static func emptyDefaultValue() -> MandatoryEnvironmentContainer {
44 | MandatoryEnvironmentContainer(value: nil)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIKit/Extension/UIColor+Extension.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import UIKit
20 |
21 | public extension UIColor {
22 | convenience init?(hex: String) {
23 | var cString: String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
24 |
25 | if cString.hasPrefix("#") {
26 | cString.remove(at: cString.startIndex)
27 | }
28 |
29 | if (cString.count) != 6 {
30 | return nil
31 | }
32 |
33 | var rgbValue: UInt64 = 0
34 | Scanner(string: cString).scanHexInt64(&rgbValue)
35 | self.init(red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
36 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
37 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
38 | alpha: 1)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIKit/Extension/Model/OrganisationAccount+Color.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import InfomaniakCore
20 | import UIKit
21 |
22 | public extension OrganisationAccount {
23 | var backgroundColor: UIColor {
24 | let nameAscii: [Int32] = name.replacingOccurrences(of: "/[^a-zA-Z ]+/",
25 | with: "",
26 | options: [.regularExpression])
27 | .compactMap { $0.asciiValue }
28 | .compactMap { Int32($0) }
29 |
30 | let hashCode: Int32 = nameAscii.reduce(0) { a, b in
31 | ((a &<< Int32(5)) &- a) &+ Int32(b)
32 | }
33 | let colorIndex = (abs(Int(hashCode)) &+ id) % 8
34 | return UIColor(named: "organisationColor\(colorIndex)")!
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIKit/Extension/UIViewController+Extension.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import UIKit
20 |
21 | public extension UIViewController {
22 | func hideKeyboardWhenTappedAround() {
23 | let tap = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
24 | tap.cancelsTouchesInView = false
25 | view.addGestureRecognizer(tap)
26 | }
27 |
28 | @objc func dismissKeyboard() {
29 | view.endEditing(true)
30 | }
31 |
32 | func okAlert(title: String, message: String?, completion: (() -> Void)? = nil) {
33 | let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
34 | alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in completion?() })
35 | present(alert, animated: true)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Utils/OrientationManager.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Mail - iOS App
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import Foundation
20 | import UIKit
21 |
22 | public protocol OrientationManageable {
23 | var orientationLock: UIInterfaceOrientationMask { get }
24 |
25 | func setOrientationLock(_ orientation: UIInterfaceOrientationMask)
26 |
27 | var interfaceOrientation: UIInterfaceOrientation? { get }
28 | }
29 |
30 | @available(iOSApplicationExtension, unavailable)
31 | public final class OrientationManager: OrientationManageable {
32 | public init() {}
33 |
34 | public var orientationLock = UIInterfaceOrientationMask.all
35 |
36 | public func setOrientationLock(_ orientation: UIInterfaceOrientationMask) {
37 | orientationLock = orientation
38 | }
39 |
40 | public var interfaceOrientation: UIInterfaceOrientation? {
41 | UIApplication.shared.mainSceneKeyWindow?.windowScene?.interfaceOrientation
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/PrivacyManagementCell.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import DesignSystem
20 | import SwiftUI
21 |
22 | @available(iOS 15.0, *)
23 | struct PrivacyManagementCell: View {
24 | let title: LocalizedStringKey
25 | var image: Image
26 |
27 | var body: some View {
28 | HStack(spacing: IKPadding.medium) {
29 | image
30 |
31 | Text(title, bundle: .module)
32 | .foregroundColor(Color("textPrimaryColor", bundle: .module))
33 | .frame(maxWidth: .infinity, alignment: .leading)
34 |
35 | Image("chevron-right", bundle: .module)
36 | .foregroundColor(Color("textSecondaryColor", bundle: .module))
37 | }
38 | .padding(IKPadding.medium)
39 | }
40 | }
41 |
42 | @available(iOS 15.0, *)
43 | #Preview {
44 | PrivacyManagementCell(title: "Matomo", image: Image("matomo-short", bundle: .module))
45 | }
46 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/SnackBar/IKSnackBarPresentable.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Mail - iOS App
3 | Copyright (C) 2022 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #if canImport(UIKit)
20 |
21 | import SnackBar
22 | import UIKit
23 |
24 | public protocol IKSnackBarPresentable {
25 | /// Show a `SnackBar` is current context
26 | func show(message: String)
27 |
28 | /// Show a `SnackBar`, with an action, is current context
29 | func show(message: String, action: IKSnackBar.Action?)
30 |
31 | /// Show a `SnackBar`, with maximum flexibility
32 | /// - Parameters:
33 | /// - message: the message to be displayed
34 | /// - duration: The duration the message should be displayed
35 | /// - action: The optional action that should be displayed
36 | /// - contextView: pass a context view in which the `SnackBar` should be displayed. Useful in complex situation.
37 | func show(
38 | message: String,
39 | duration: SnackBar.Duration,
40 | action: IKSnackBar.Action?,
41 | contextView: UIView?
42 | )
43 | }
44 | #endif
45 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIResources/Localizable/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | * Loco ios export: Xcode Strings (legacy)
3 | * Project: CoreUI
4 | * Locale: en, English
5 | * Tagged: ios, !emoji-reaction, !inapp2fa, !interapplogin, !ios-stringsdict, !kSuite, !kSuiteUtils, !my kSuite, !privacy
6 | * Exported by: Philippe Weidmann
7 | * Exported at: Thu, 25 Sep 2025 12:51:07 +0200
8 | */
9 |
10 | /* loco:675fea0d40923b5c440f0f52 */
11 | "anErrorHasOccurred" = "An error has occurred";
12 |
13 | /* loco:6729ea9f4cb9f889f604d934 */
14 | "buttonCancel" = "Cancel";
15 |
16 | /* loco:679237f6daa3807fa008b175 */
17 | "buttonClose" = "Close";
18 |
19 | /* loco:67ac7d178defcfcd7806e182 */
20 | "buttonLater" = "Later";
21 |
22 | /* loco:675059634bdf0aedde06df72 */
23 | "buttonNext" = "Next";
24 |
25 | /* loco:67beed573c592678eb085582 */
26 | "buttonNo" = "No";
27 |
28 | /* loco:6729ead76f93fd246802f932 */
29 | "buttonRetry" = "Retry";
30 |
31 | /* loco:682dc3dd2d87d3cbda04b3a2 */
32 | "buttonSave" = "Save";
33 |
34 | /* loco:685d08b2fc3b99693f00c872 */
35 | "buttonUploadFromCamera" = "Camera";
36 |
37 | /* loco:685d0914ecd5fc13620f1fc2 */
38 | "buttonUploadFromFiles" = "Browse files";
39 |
40 | /* loco:685d08dc653f4deb94019b62 */
41 | "buttonUploadFromGallery" = "Photo and video gallery";
42 |
43 | /* loco:67beed7f8291a886220faf53 */
44 | "buttonYes" = "Yes";
45 |
46 | /* loco:676538295907d1ab51014ae2 */
47 | "errorDownload" = "Download error";
48 |
49 | /* loco:67653882015fa8304b01cbb9 */
50 | "errorDownloadInsufficientSpace" = "Cannot download: Insufficient space";
51 |
52 | /* loco:67dbc1f28c22b8594f030f32 */
53 | "joinTheBetaButton" = "Join the beta program";
54 |
55 | /* loco:67beee584d2044470e0df152 */
56 | "reviewAlertTitle" = "Do you like %@?";
57 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Modifiers/CompactWindowDetectorModifier.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2024 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 |
21 | public extension EnvironmentValues {
22 | @Entry
23 | var isCompactWindow = true
24 | }
25 |
26 | public extension View {
27 | func detectCompactWindow() -> some View {
28 | modifier(CompactWindowDetectorModifier())
29 | }
30 | }
31 |
32 | public struct CompactWindowDetectorModifier: ViewModifier {
33 | @Environment(\.horizontalSizeClass) private var horizontalSizeClass
34 | @Environment(\.verticalSizeClass) private var verticalSizeClass
35 |
36 | @State private var isCompactWindow = true
37 |
38 | public func body(content: Content) -> some View {
39 | content
40 | .environment(\.isCompactWindow, isCompactWindow)
41 | .task(id: horizontalSizeClass == .compact || verticalSizeClass == .compact) {
42 | isCompactWindow = horizontalSizeClass == .compact || verticalSizeClass == .compact
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Assets.xcassets/Files/Images/file-pdf.imageset/file-pdf.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/AvatarView/InitialsView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 |
21 | public struct InitialsView: View {
22 | let initials: String
23 | let backgroundColor: Color
24 | let foregroundColor: Color
25 | let size: CGFloat
26 |
27 | public init(initials: String, backgroundColor: Color, foregroundColor: Color, size: CGFloat) {
28 | self.initials = initials
29 | self.backgroundColor = backgroundColor
30 | self.foregroundColor = foregroundColor
31 | self.size = size
32 | }
33 |
34 | public var body: some View {
35 | ZStack {
36 | Circle()
37 | .fill(backgroundColor)
38 | Text(initials)
39 | .font(.system(size: size * 0.5, weight: .semibold))
40 | .foregroundStyle(foregroundColor)
41 | }
42 | .frame(width: size, height: size)
43 | }
44 | }
45 |
46 | #Preview {
47 | InitialsView(initials: "TE", backgroundColor: .red, foregroundColor: .white, size: 40)
48 | }
49 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIResources/Localizable/es.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | * Loco ios export: Xcode Strings (legacy)
3 | * Project: CoreUI
4 | * Locale: es, Spanish
5 | * Tagged: ios, !emoji-reaction, !inapp2fa, !interapplogin, !ios-stringsdict, !kSuite, !kSuiteUtils, !my kSuite, !privacy
6 | * Exported by: Philippe Weidmann
7 | * Exported at: Thu, 25 Sep 2025 12:51:07 +0200
8 | */
9 |
10 | /* loco:675fea0d40923b5c440f0f52 */
11 | "anErrorHasOccurred" = "Se ha producido un error";
12 |
13 | /* loco:6729ea9f4cb9f889f604d934 */
14 | "buttonCancel" = "Cancelar";
15 |
16 | /* loco:679237f6daa3807fa008b175 */
17 | "buttonClose" = "Cerrar";
18 |
19 | /* loco:67ac7d178defcfcd7806e182 */
20 | "buttonLater" = "Más tarde";
21 |
22 | /* loco:675059634bdf0aedde06df72 */
23 | "buttonNext" = "Siguiente";
24 |
25 | /* loco:67beed573c592678eb085582 */
26 | "buttonNo" = "No";
27 |
28 | /* loco:6729ead76f93fd246802f932 */
29 | "buttonRetry" = "Reintentar";
30 |
31 | /* loco:682dc3dd2d87d3cbda04b3a2 */
32 | "buttonSave" = "Guardar";
33 |
34 | /* loco:685d08b2fc3b99693f00c872 */
35 | "buttonUploadFromCamera" = "Cámara";
36 |
37 | /* loco:685d0914ecd5fc13620f1fc2 */
38 | "buttonUploadFromFiles" = "Examinar archivos";
39 |
40 | /* loco:685d08dc653f4deb94019b62 */
41 | "buttonUploadFromGallery" = "Galería de fotos y vídeos";
42 |
43 | /* loco:67beed7f8291a886220faf53 */
44 | "buttonYes" = "Sí";
45 |
46 | /* loco:676538295907d1ab51014ae2 */
47 | "errorDownload" = "Error al descargar";
48 |
49 | /* loco:67653882015fa8304b01cbb9 */
50 | "errorDownloadInsufficientSpace" = "No se puede descargar: espacio insuficiente";
51 |
52 | /* loco:67dbc1f28c22b8594f030f32 */
53 | "joinTheBetaButton" = "Unirse al programa beta";
54 |
55 | /* loco:67beee584d2044470e0df152 */
56 | "reviewAlertTitle" = "¿Te gusta %@?";
57 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIKit/Extension/UIView+Extension.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import UIKit
20 |
21 | public extension UIView {
22 | @IBInspectable var cornerRadius: CGFloat {
23 | get {
24 | return layer.cornerRadius
25 | }
26 | set {
27 | layer.cornerRadius = newValue
28 | }
29 | }
30 |
31 | @IBInspectable var borderWidth: CGFloat {
32 | get {
33 | return layer.borderWidth
34 | }
35 | set {
36 | layer.borderWidth = newValue
37 | }
38 | }
39 |
40 | @IBInspectable var borderColor: UIColor? {
41 | get {
42 | return UIColor(cgColor: layer.borderColor!)
43 | }
44 | set {
45 | layer.borderColor = newValue?.cgColor
46 | }
47 | }
48 |
49 | func roundCorners(corners: CACornerMask, radius: CGFloat) {
50 | clipsToBounds = false
51 | layer.cornerRadius = radius
52 | #if !os(tvOS)
53 | layer.maskedCorners = corners
54 | #endif
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIResources/Localizable/it.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | * Loco ios export: Xcode Strings (legacy)
3 | * Project: CoreUI
4 | * Locale: it, Italian
5 | * Tagged: ios, !emoji-reaction, !inapp2fa, !interapplogin, !ios-stringsdict, !kSuite, !kSuiteUtils, !my kSuite, !privacy
6 | * Exported by: Philippe Weidmann
7 | * Exported at: Thu, 25 Sep 2025 12:51:07 +0200
8 | */
9 |
10 | /* loco:675fea0d40923b5c440f0f52 */
11 | "anErrorHasOccurred" = "Si è verificato un errore";
12 |
13 | /* loco:6729ea9f4cb9f889f604d934 */
14 | "buttonCancel" = "Annulla";
15 |
16 | /* loco:679237f6daa3807fa008b175 */
17 | "buttonClose" = "Chiudere";
18 |
19 | /* loco:67ac7d178defcfcd7806e182 */
20 | "buttonLater" = "Più tardi";
21 |
22 | /* loco:675059634bdf0aedde06df72 */
23 | "buttonNext" = "Avanti";
24 |
25 | /* loco:67beed573c592678eb085582 */
26 | "buttonNo" = "No";
27 |
28 | /* loco:6729ead76f93fd246802f932 */
29 | "buttonRetry" = "Riprova";
30 |
31 | /* loco:682dc3dd2d87d3cbda04b3a2 */
32 | "buttonSave" = "Salva";
33 |
34 | /* loco:685d08b2fc3b99693f00c872 */
35 | "buttonUploadFromCamera" = "Macchina fotografica";
36 |
37 | /* loco:685d0914ecd5fc13620f1fc2 */
38 | "buttonUploadFromFiles" = "Sfoglia i file";
39 |
40 | /* loco:685d08dc653f4deb94019b62 */
41 | "buttonUploadFromGallery" = "Galleria di foto e video";
42 |
43 | /* loco:67beed7f8291a886220faf53 */
44 | "buttonYes" = "Sì";
45 |
46 | /* loco:676538295907d1ab51014ae2 */
47 | "errorDownload" = "Errore durante il download";
48 |
49 | /* loco:67653882015fa8304b01cbb9 */
50 | "errorDownloadInsufficientSpace" = "Impossibile scaricare: spazio insufficiente";
51 |
52 | /* loco:67dbc1f28c22b8594f030f32 */
53 | "joinTheBetaButton" = "Partecipa al programma beta";
54 |
55 | /* loco:67beee584d2044470e0df152 */
56 | "reviewAlertTitle" = "Ti piace %@?";
57 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIResources/Localizable/de.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | * Loco ios export: Xcode Strings (legacy)
3 | * Project: CoreUI
4 | * Locale: de, German
5 | * Tagged: ios, !emoji-reaction, !inapp2fa, !interapplogin, !ios-stringsdict, !kSuite, !kSuiteUtils, !my kSuite, !privacy
6 | * Exported by: Philippe Weidmann
7 | * Exported at: Thu, 25 Sep 2025 12:51:07 +0200
8 | */
9 |
10 | /* loco:675fea0d40923b5c440f0f52 */
11 | "anErrorHasOccurred" = "Ein Fehler ist aufgetreten";
12 |
13 | /* loco:6729ea9f4cb9f889f604d934 */
14 | "buttonCancel" = "Abbrechen";
15 |
16 | /* loco:679237f6daa3807fa008b175 */
17 | "buttonClose" = "Schliessen";
18 |
19 | /* loco:67ac7d178defcfcd7806e182 */
20 | "buttonLater" = "Später";
21 |
22 | /* loco:675059634bdf0aedde06df72 */
23 | "buttonNext" = "Weiter";
24 |
25 | /* loco:67beed573c592678eb085582 */
26 | "buttonNo" = "Nein";
27 |
28 | /* loco:6729ead76f93fd246802f932 */
29 | "buttonRetry" = "Wiederholen";
30 |
31 | /* loco:682dc3dd2d87d3cbda04b3a2 */
32 | "buttonSave" = "Speichern";
33 |
34 | /* loco:685d08b2fc3b99693f00c872 */
35 | "buttonUploadFromCamera" = "Kamera";
36 |
37 | /* loco:685d0914ecd5fc13620f1fc2 */
38 | "buttonUploadFromFiles" = "Dateien durchsuchen";
39 |
40 | /* loco:685d08dc653f4deb94019b62 */
41 | "buttonUploadFromGallery" = "Foto- und Videogalerie";
42 |
43 | /* loco:67beed7f8291a886220faf53 */
44 | "buttonYes" = "Ja";
45 |
46 | /* loco:676538295907d1ab51014ae2 */
47 | "errorDownload" = "Fehler beim Download";
48 |
49 | /* loco:67653882015fa8304b01cbb9 */
50 | "errorDownloadInsufficientSpace" = "Download nicht möglich: Unzureichender Speicherplatz";
51 |
52 | /* loco:67dbc1f28c22b8594f030f32 */
53 | "joinTheBetaButton" = "Dem Beta-Programm beitreten";
54 |
55 | /* loco:67beee584d2044470e0df152 */
56 | "reviewAlertTitle" = "Mögen Sie %@?";
57 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIResources/Localizable/fr.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | * Loco ios export: Xcode Strings (legacy)
3 | * Project: CoreUI
4 | * Locale: fr, French
5 | * Tagged: ios, !emoji-reaction, !inapp2fa, !interapplogin, !ios-stringsdict, !kSuite, !kSuiteUtils, !my kSuite, !privacy
6 | * Exported by: Philippe Weidmann
7 | * Exported at: Thu, 25 Sep 2025 12:51:07 +0200
8 | */
9 |
10 | /* loco:675fea0d40923b5c440f0f52 */
11 | "anErrorHasOccurred" = "Une erreur est survenue";
12 |
13 | /* loco:6729ea9f4cb9f889f604d934 */
14 | "buttonCancel" = "Annuler";
15 |
16 | /* loco:679237f6daa3807fa008b175 */
17 | "buttonClose" = "Fermer";
18 |
19 | /* loco:67ac7d178defcfcd7806e182 */
20 | "buttonLater" = "Plus tard";
21 |
22 | /* loco:675059634bdf0aedde06df72 */
23 | "buttonNext" = "Suivant";
24 |
25 | /* loco:67beed573c592678eb085582 */
26 | "buttonNo" = "Non";
27 |
28 | /* loco:6729ead76f93fd246802f932 */
29 | "buttonRetry" = "Réessayer";
30 |
31 | /* loco:682dc3dd2d87d3cbda04b3a2 */
32 | "buttonSave" = "Enregistrer";
33 |
34 | /* loco:685d08b2fc3b99693f00c872 */
35 | "buttonUploadFromCamera" = "Appareil photo";
36 |
37 | /* loco:685d0914ecd5fc13620f1fc2 */
38 | "buttonUploadFromFiles" = "Parcourir les fichiers";
39 |
40 | /* loco:685d08dc653f4deb94019b62 */
41 | "buttonUploadFromGallery" = "Galerie photos et vidéos";
42 |
43 | /* loco:67beed7f8291a886220faf53 */
44 | "buttonYes" = "Oui";
45 |
46 | /* loco:676538295907d1ab51014ae2 */
47 | "errorDownload" = "Erreur lors du téléchargement";
48 |
49 | /* loco:67653882015fa8304b01cbb9 */
50 | "errorDownloadInsufficientSpace" = "Téléchargement impossible : Espace insuffisant";
51 |
52 | /* loco:67dbc1f28c22b8594f030f32 */
53 | "joinTheBetaButton" = "Rejoindre le programme bêta";
54 |
55 | /* loco:67beee584d2044470e0df152 */
56 | "reviewAlertTitle" = "Vous aimez %@ ?";
57 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Alignment/IconAndMultilineTextAlignment.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 |
21 | public extension VerticalAlignment {
22 | /// Alignment ID used for the icon and the text
23 | /// The icon must be vertically centered with the first line of the text
24 | enum IconAndMultilineTextAlignment: AlignmentID {
25 | public static func defaultValue(in context: ViewDimensions) -> CGFloat {
26 | return context[.top]
27 | }
28 | }
29 |
30 | static let iconAndMultilineTextAlignment = VerticalAlignment(IconAndMultilineTextAlignment.self)
31 | }
32 |
33 | public extension View {
34 | func verticalAlignmentGuideForIcon() -> some View {
35 | alignmentGuide(.iconAndMultilineTextAlignment) { d in
36 | d[VerticalAlignment.center]
37 | }
38 | }
39 |
40 | func verticalAlignmentGuideForMultilineText() -> some View {
41 | alignmentGuide(.iconAndMultilineTextAlignment) { d in
42 | (d.height - (d[.lastTextBaseline] - d[.firstTextBaseline])) / 2
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/SnackBar/IKWindow.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Mail - iOS App
3 | Copyright (C) 2022 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #if canImport(UIKit)
20 |
21 | import UIKit
22 |
23 | final class IKWindow: UIWindow {
24 | init(with rootVC: UIViewController) {
25 | if let scene = UIApplication.shared.connectedScenes
26 | .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
27 | super.init(windowScene: scene)
28 | } else {
29 | super.init(frame: UIScreen.main.bounds)
30 | }
31 | backgroundColor = .clear
32 | rootViewController = rootVC
33 | accessibilityViewIsModal = true
34 | }
35 |
36 | @available(*, unavailable)
37 | required init?(coder: NSCoder) {
38 | fatalError("init(coder:) has not been implemented")
39 | }
40 |
41 | override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
42 | if let rootViewController = IKWindowProvider.shared.rootViewController {
43 | return rootViewController.view.hitTest(point, with: event)
44 | }
45 | return nil
46 | }
47 | }
48 |
49 | #endif
50 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIKit/UIButton/UIButton+Extension.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import UIKit
20 |
21 | public extension UIButton {
22 | func setLoading(_ loading: Bool, style: UIActivityIndicatorView.Style = .medium) {
23 | isEnabled = !loading
24 | if loading {
25 | setTitle("", for: .disabled)
26 | let loadingSpinner = UIActivityIndicatorView(style: style)
27 | loadingSpinner.startAnimating()
28 | loadingSpinner.translatesAutoresizingMaskIntoConstraints = false
29 | loadingSpinner.hidesWhenStopped = true
30 | addSubview(loadingSpinner)
31 | loadingSpinner.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
32 | loadingSpinner.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
33 | } else {
34 | setTitle(title(for: .normal), for: .disabled)
35 | for view in subviews {
36 | if view.isKind(of: UIActivityIndicatorView.self) {
37 | view.removeFromSuperview()
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Sources/DesignSystem/DesignTokens/IKPadding.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import Foundation
20 |
21 | /// An enumeration to list the paddings used for Infomaniak apps.
22 | @frozen public enum IKPadding {
23 | @frozen public enum Option: CGFloat {
24 | /// 4pt padding
25 | case micro = 4
26 | /// 8pt padding
27 | case mini = 8
28 | /// 12pt padding
29 | case small = 12
30 | /// 16pt padding
31 | case medium = 16
32 | /// 24pt padding
33 | case large = 24
34 | /// 48pt padding
35 | case huge = 32
36 | /// 48pt padding
37 | case giant = 48
38 | }
39 |
40 | /// 4pt padding
41 | public static let micro: CGFloat = 4
42 | /// 8pt padding
43 | public static let mini: CGFloat = 8
44 | /// 12pt padding
45 | public static let small: CGFloat = 12
46 | /// 16pt padding
47 | public static let medium: CGFloat = 16
48 | /// 24pt padding
49 | public static let large: CGFloat = 24
50 | /// 32pt padding
51 | public static let huge: CGFloat = 32
52 | /// 48pt padding
53 | public static let giant: CGFloat = 48
54 | }
55 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Localizable/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | * Loco ios export: Xcode Strings (legacy)
3 | * Project: CoreUI
4 | * Locale: en, English
5 | * Tagged: ios
6 | * Exported by: Baptiste Griva
7 | * Exported at: Tue, 30 Sep 2025 09:48:07 +0200
8 | */
9 |
10 | /* loco:679b18c9e56503c64e0f47b2 */
11 | "applicationSourceCode" = "See source code";
12 |
13 | /* loco:679b16a81b0e3541200e1672 */
14 | "authorizeTracking" = "Authorize tracking";
15 |
16 | /* loco:679b17a8f70dbaf41b0c3c92 */
17 | "trackingManagementDescription" = "At Infomaniak, your data is never a bargaining chip. We only use in-house tools, hosted and controlled by ourselves, to guarantee the quality and evolution of our applications.\n\nThis technical data is confidential, stored on our own servers in Switzerland, accessible only to our development teams, and never shared with third parties. Application source code can be verified, guaranteeing total transparency.";
18 |
19 | /* loco:679b1726759efd28eb0aae82 */
20 | "trackingManagementTitle" = "Data management";
21 |
22 | /* loco:679b1934489a90910a02ef02 */
23 | "trackingMatomoDescription" = "Matomo is an analysis tool hosted and managed exclusively by Infomaniak to understand how the application is used.\n\nBy studying this data, our team is able to continually improve the application’s interface.";
24 |
25 | /* loco:679b19a71cbd373edb0fcc92 */
26 | "trackingMatomoTitle" = "Matomo";
27 |
28 | /* loco:679b19effce81c25230ef922 */
29 | "trackingSentryDescription" = "Sentry is a tool hosted and managed exclusively by Infomaniak to monitor the stability of the application in real time and automatically report any technical errors to our developers.\n\nThis data enables our team to quickly correct and optimise the application, resulting in a better user experience for you.";
30 |
31 | /* loco:679b1a63d5844c9d0d041fb2 */
32 | "trackingSentryTitle" = "Sentry";
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/swiftpackagemanager,macos,xcode
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=swiftpackagemanager,macos,xcode
3 |
4 | ### macOS ###
5 | # General
6 | .DS_Store
7 | .AppleDouble
8 | .LSOverride
9 |
10 | # Icon must end with two \r
11 | Icon
12 |
13 | # Thumbnails
14 | ._*
15 |
16 | # Files that might appear in the root of a volume
17 | .DocumentRevisions-V100
18 | .fseventsd
19 | .Spotlight-V100
20 | .TemporaryItems
21 | .Trashes
22 | .VolumeIcon.icns
23 | .com.apple.timemachine.donotpresent
24 |
25 | # Directories potentially created on remote AFP share
26 | .AppleDB
27 | .AppleDesktop
28 | Network Trash Folder
29 | Temporary Items
30 | .apdisk
31 |
32 | ### SwiftPackageManager ###
33 | Packages
34 | .build/
35 | xcuserdata
36 | DerivedData/
37 | *.xcodeproj
38 |
39 |
40 | ### Xcode ###
41 | # Xcode
42 | #
43 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
44 |
45 | ## User settings
46 | xcuserdata/
47 |
48 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
49 | *.xcscmblueprint
50 | *.xccheckout
51 |
52 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
53 | build/
54 | *.moved-aside
55 | *.pbxuser
56 | !default.pbxuser
57 | *.mode1v3
58 | !default.mode1v3
59 | *.mode2v3
60 | !default.mode2v3
61 | *.perspectivev3
62 | !default.perspectivev3
63 |
64 | ## Gcc Patch
65 | /*.gcno
66 |
67 | ### Xcode Patch ###
68 | *.xcodeproj/*
69 | !*.xcodeproj/project.pbxproj
70 | !*.xcodeproj/xcshareddata/
71 | !*.xcworkspace/contents.xcworkspacedata
72 | **/xcshareddata/WorkspaceSettings.xcsettings
73 |
74 | # End of https://www.toptal.com/developers/gitignore/api/swiftpackagemanager,macos,xcode%
75 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIKit/UILabel/IKLabel.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #if os(macOS)
20 | import AppKit
21 | #elseif os(iOS)
22 | import UIKit
23 | #elseif os(tvOS) || os(watchOS)
24 | import UIKit
25 | #endif
26 |
27 | import InfomaniakCoreCommonUI
28 |
29 | @IBDesignable public class IKLabel: UILabel {
30 | /// Set label style.
31 | @IBInspectable public var styleName: String = TextStyle.body1.rawValue {
32 | didSet { setUpLabel() }
33 | }
34 |
35 | /// Set label style.
36 | public var style: TextStyle {
37 | get {
38 | return TextStyle(rawValue: styleName) ?? .body1
39 | }
40 | set {
41 | styleName = newValue.rawValue
42 | }
43 | }
44 |
45 | override public init(frame: CGRect) {
46 | super.init(frame: frame)
47 | setUpLabel()
48 | }
49 |
50 | required init?(coder: NSCoder) {
51 | super.init(coder: coder)
52 | setUpLabel()
53 | }
54 |
55 | override public func prepareForInterfaceBuilder() {
56 | super.prepareForInterfaceBuilder()
57 | setUpLabel()
58 | }
59 |
60 | func setUpLabel() {
61 | font = style.font
62 | textColor = style.color
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | disabled_rules:
2 | - line_length
3 | - identifier_name
4 | - type_body_length
5 | - function_body_length
6 | - file_length
7 | - type_name
8 | - force_cast
9 | - cyclomatic_complexity
10 | - inclusive_language
11 | - for_where
12 | - optional_data_string_conversion
13 | opt_in_rules:
14 | - closure_end_indentation
15 | - closure_spacing
16 | - collection_alignment
17 | - contains_over_filter_count
18 | - contains_over_first_not_nil
19 | - contains_over_range_nil_comparison
20 | - empty_collection_literal
21 | - empty_count
22 | - empty_string
23 | - first_where
24 | - identical_operands
25 | - last_where
26 | - operator_usage_whitespace
27 | - overridden_super_call
28 | - prefer_zero_over_explicit_init
29 | - prohibited_super_call
30 | - redundant_type_annotation
31 | - toggle_bool
32 | - trailing_closure
33 | - unneeded_parentheses_in_closure_argument
34 | analyzer_rules:
35 | - unused_import
36 | excluded:
37 | - Derived/Sources/*
38 | - DerivedData/
39 | - Derived/
40 | - Tuist/.build/
41 | - Tests/*
42 | - Sources/InfomaniakCoreUIResources/Generated/*
43 | custom_rules:
44 | private_state:
45 | included:
46 | - ".*\\.swift"
47 | regex: "(?.
17 | */
18 |
19 | import SwiftUI
20 |
21 | public extension Font {
22 | /// Create a custom font with the UIFont preferred font family.
23 | /// - Parameters:
24 | /// - size: Default size of the font for the "large" `Dynamic Type Size`.
25 | /// - weight: Weight of the font.
26 | /// - textStyle: The text style on which the font will be based to scale.
27 | ///
28 | /// - Returns: A font with the specified attributes.
29 | ///
30 | /// SwiftUI will use the default system font with the specified weight and size use `Dynamic Type Size`.
31 | static func dynamicTypeSizeFont(size: CGFloat, weight: Weight, relativeTo textStyle: TextStyle) -> Font {
32 | #if canImport(UIKit)
33 | let fontFamily = UIFont.preferredFont(forTextStyle: .body).familyName
34 | return custom(fontFamily, size: size, relativeTo: textStyle).weight(weight)
35 | #elseif canImport(AppKit)
36 | let fontFamily = NSFont.preferredFont(forTextStyle: .body).familyName
37 | return custom(fontFamily, size: size, relativeTo: textStyle).weight(weight)
38 | #else
39 | fatalError("Unsupported UI platform")
40 | #endif
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/FloatingPanelCloseButton.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2024 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import DesignSystem
20 | import SwiftUI
21 |
22 | @available(iOS 15.0, *)
23 | public struct FloatingPanelCloseButton: View {
24 | let size: IKIconSize?
25 | let dismissHandler: () -> Void
26 |
27 | public init(size: IKIconSize? = nil, dismissHandler: @escaping () -> Void) {
28 | self.size = size
29 | self.dismissHandler = dismissHandler
30 | }
31 |
32 | public init(size: IKIconSize? = nil, dismissAction: DismissAction) {
33 | self.size = size
34 | dismissHandler = dismissAction.callAsFunction
35 | }
36 |
37 | public var body: some View {
38 | Button(action: dismissHandler) {
39 | Label {
40 | Text("Close", bundle: .module)
41 | } icon: {
42 | Image(systemName: "xmark")
43 | .resizable()
44 | .scaledToFit()
45 | .frame(width: size?.rawValue, height: size?.rawValue)
46 | }
47 | }
48 | .labelStyle(.iconOnly)
49 | .keyboardShortcut(.cancelAction)
50 | }
51 | }
52 |
53 | @available(iOS 15.0, *)
54 | #Preview {
55 | FloatingPanelCloseButton { /* Preview */ }
56 | }
57 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Tracker.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 |
21 | public enum Tracker: String, CaseIterable, Identifiable {
22 | case matomo
23 | case sentry
24 |
25 | public var id: String { rawValue }
26 |
27 | public var title: LocalizedStringKey {
28 | switch self {
29 | case .matomo:
30 | return "trackingMatomoTitle"
31 | case .sentry:
32 | return "trackingSentryTitle"
33 | }
34 | }
35 |
36 | public var description: String {
37 | switch self {
38 | case .matomo:
39 | return "trackingMatomoDescription"
40 | case .sentry:
41 | return "trackingSentryDescription"
42 | }
43 | }
44 |
45 | public var logoShort: Image {
46 | switch self {
47 | case .matomo:
48 | return Image("matomo-short", bundle: .module)
49 | case .sentry:
50 | return Image("sentry-short", bundle: .module)
51 | }
52 | }
53 |
54 | public var logoLong: Image {
55 | switch self {
56 | case .matomo:
57 | return Image("matomo-long", bundle: .module)
58 | case .sentry:
59 | return Image("sentry-long", bundle: .module)
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Localizable/it.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | * Loco ios export: Xcode Strings (legacy)
3 | * Project: CoreUI
4 | * Locale: it, Italian
5 | * Tagged: ios
6 | * Exported by: Baptiste Griva
7 | * Exported at: Tue, 30 Sep 2025 09:48:07 +0200
8 | */
9 |
10 | /* loco:679b18c9e56503c64e0f47b2 */
11 | "applicationSourceCode" = "Vedi il codice sorgente";
12 |
13 | /* loco:679b16a81b0e3541200e1672 */
14 | "authorizeTracking" = "Autorizzare il tracciamento";
15 |
16 | /* loco:679b17a8f70dbaf41b0c3c92 */
17 | "trackingManagementDescription" = "In Infomaniak, i vostri dati non sono mai merce di scambio. Utilizziamo solo strumenti interni, ospitati e controllati da noi stessi, per garantire la qualità e lo sviluppo delle nostre applicazioni.\n\nQuesti dati tecnici sono riservati, archiviati sui nostri server in Svizzera, accessibili solo ai nostri team di sviluppo e non vengono mai condivisi con terzi. Il codice sorgente delle nostre applicazioni può essere verificato, garantendo una trasparenza totale.";
18 |
19 | /* loco:679b1726759efd28eb0aae82 */
20 | "trackingManagementTitle" = "Gestione dei dati";
21 |
22 | /* loco:679b1934489a90910a02ef02 */
23 | "trackingMatomoDescription" = "Matomo è uno strumento di analisi ospitato e gestito esclusivamente da Infomaniak per capire come viene utilizzata l’applicazione.\n\nStudiando questi dati, il nostro team è in grado di migliorare continuamente l’interfaccia dell’applicazione.";
24 |
25 | /* loco:679b19a71cbd373edb0fcc92 */
26 | "trackingMatomoTitle" = "Matomo";
27 |
28 | /* loco:679b19effce81c25230ef922 */
29 | "trackingSentryDescription" = "Sentry è uno strumento ospitato e gestito esclusivamente da Infomaniak per monitorare la stabilità dell’applicazione in tempo reale e segnalare automaticamente eventuali errori tecnici ai nostri sviluppatori.\n\nQuesti dati consentono al nostro team di correggere e ottimizzare rapidamente l’applicazione, migliorando l’esperienza dell’utente.";
30 |
31 | /* loco:679b1a63d5844c9d0d041fb2 */
32 | "trackingSentryTitle" = "Sentry";
33 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/ThemedLottieView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import Lottie
20 | import SwiftUI
21 |
22 | public struct ThemedLottieView: View {
23 | @Environment(\.colorScheme) private var colorScheme
24 |
25 | let lightAnimationName: String
26 | let darkAnimationName: String?
27 |
28 | let bundle: Bundle
29 |
30 | let loopMode: Lottie.LottieLoopMode
31 |
32 | private var animationName: String {
33 | if colorScheme == .dark,
34 | let darkAnimationName {
35 | return darkAnimationName
36 | } else {
37 | return lightAnimationName
38 | }
39 | }
40 |
41 | public init(
42 | lightAnimationName: String,
43 | darkAnimationName: String? = nil,
44 | bundle: Bundle,
45 | loopMode: Lottie.LottieLoopMode = .autoReverse
46 | ) {
47 | self.lightAnimationName = lightAnimationName
48 | self.darkAnimationName = darkAnimationName
49 | self.bundle = bundle
50 | self.loopMode = loopMode
51 | }
52 |
53 | public var body: some View {
54 | LottieView {
55 | try await LottieAnimationSource.dotLottieFile(.named(animationName, bundle: bundle))
56 | }
57 | .playing(loopMode: loopMode)
58 | .id(colorScheme)
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Helpers/FileType/FileTypeProvider.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2024 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 | import UniformTypeIdentifiers
21 |
22 | @available(iOS 14.0, *)
23 | public struct FileTypeProvider: Sendable {
24 | private static let checkableFileTypes: [FileType] = [
25 | .archive, .audio, .video, .image, .pdf, .ics, .font, .grid, .point, .doc, .code
26 | ]
27 |
28 | public let uti: UTType?
29 | public let fileType: FileType
30 |
31 | public var image: Image {
32 | fileType.image
33 | }
34 |
35 | public var color: Color {
36 | fileType.color
37 | }
38 |
39 | public init(identifier: String) {
40 | self.init(uti: UTType(identifier))
41 | }
42 |
43 | public init(mimeType: String) {
44 | self.init(uti: UTType(mimeType: mimeType))
45 | }
46 |
47 | public init(uti: UTType?) {
48 | self.uti = uti
49 | fileType = FileTypeProvider.guessFileType(from: uti)
50 | }
51 |
52 | private static func guessFileType(from type: UTType?) -> FileType {
53 | guard let type else { return .unknown }
54 |
55 | for fileType in checkableFileTypes {
56 | if fileType.conforms(to: type) {
57 | return fileType
58 | }
59 | }
60 |
61 | return .unknown
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Localizable/fr.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | * Loco ios export: Xcode Strings (legacy)
3 | * Project: CoreUI
4 | * Locale: fr, French
5 | * Tagged: ios
6 | * Exported by: Baptiste Griva
7 | * Exported at: Tue, 30 Sep 2025 09:48:07 +0200
8 | */
9 |
10 | /* loco:679b18c9e56503c64e0f47b2 */
11 | "applicationSourceCode" = "Voir le code source";
12 |
13 | /* loco:679b16a81b0e3541200e1672 */
14 | "authorizeTracking" = "Autoriser le suivi";
15 |
16 | /* loco:679b17a8f70dbaf41b0c3c92 */
17 | "trackingManagementDescription" = "Chez Infomaniak, vos données ne sont jamais une monnaie d’échange. Nous utilisons uniquement des outils internes, hébergés et maîtrisés par nos soins, pour garantir la qualité et l’évolution de nos applications.\n\nCes données techniques sont confidentielles, stockées sur nos propres serveurs en Suisse, accessibles uniquement à nos équipes de développement, et ne sont jamais partagées avec des tiers. Le code source des applications peut être vérifié, garantissant une transparence totale.";
18 |
19 | /* loco:679b1726759efd28eb0aae82 */
20 | "trackingManagementTitle" = "Gestion des données";
21 |
22 | /* loco:679b1934489a90910a02ef02 */
23 | "trackingMatomoDescription" = "Matomo est un outil d’analyse hébergé et géré exclusivement par Infomaniak pour comprendre comment l’application est utilisée.\n\nL’étude de ces données permet à notre équipe d’améliorer en continue l’interface de l’application.";
24 |
25 | /* loco:679b19a71cbd373edb0fcc92 */
26 | "trackingMatomoTitle" = "Matomo";
27 |
28 | /* loco:679b19effce81c25230ef922 */
29 | "trackingSentryDescription" = "Sentry est un outil hébergé et géré exclusivement par Infomaniak pour surveiller en temps réel la stabilité de l’application et signaler automatiquement d’éventuelles erreurs techniques à nos développeurs.\n\nCes données permettent à notre équipe de rapidement corriger et optimiser l’application, ce qui se traduit par une meilleure expérience d’utilisation pour vous.";
30 |
31 | /* loco:679b1a63d5844c9d0d041fb2 */
32 | "trackingSentryTitle" = "Sentry";
33 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Localizable/es.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | * Loco ios export: Xcode Strings (legacy)
3 | * Project: CoreUI
4 | * Locale: es, Spanish
5 | * Tagged: ios
6 | * Exported by: Baptiste Griva
7 | * Exported at: Tue, 30 Sep 2025 09:48:07 +0200
8 | */
9 |
10 | /* loco:679b18c9e56503c64e0f47b2 */
11 | "applicationSourceCode" = "Ver código fuente";
12 |
13 | /* loco:679b16a81b0e3541200e1672 */
14 | "authorizeTracking" = "Autorizar el seguimiento";
15 |
16 | /* loco:679b17a8f70dbaf41b0c3c92 */
17 | "trackingManagementDescription" = "En Infomaniak, sus datos nunca son moneda de cambio. Solo utilizamos herramientas internas, alojadas y controladas por nosotros mismos, para garantizar la calidad y el desarrollo de nuestras aplicaciones.\n\nEstos datos técnicos son confidenciales, se almacenan en nuestros propios servidores en Suiza, sólo son accesibles a nuestros equipos de desarrollo y nunca se comparten con terceros. El código fuente de nuestras aplicaciones puede verificarse, lo que garantiza una total transparencia.";
18 |
19 | /* loco:679b1726759efd28eb0aae82 */
20 | "trackingManagementTitle" = "Gestión de datos";
21 |
22 | /* loco:679b1934489a90910a02ef02 */
23 | "trackingMatomoDescription" = "Matomo es una herramienta de análisis alojada y gestionada exclusivamente por Infomaniak para comprender cómo se utiliza la aplicación.\n\nEl estudio de estos datos permite a nuestro equipo mejorar continuamente la interfaz de la aplicación.";
24 |
25 | /* loco:679b19a71cbd373edb0fcc92 */
26 | "trackingMatomoTitle" = "Matomo";
27 |
28 | /* loco:679b19effce81c25230ef922 */
29 | "trackingSentryDescription" = "Sentry es una herramienta alojada y gestionada en exclusiva por Infomaniak para supervisar la estabilidad de la aplicación en tiempo real e informar automáticamente de cualquier error técnico a nuestros desarrolladores.\n\nEstos datos permiten a nuestro equipo corregir y optimizar rápidamente la aplicación, lo que se traduce en una mejor experiencia de usuario para usted.";
30 |
31 | /* loco:679b1a63d5844c9d0d041fb2 */
32 | "trackingSentryTitle" = "Sentry";
33 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Localizable/de.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | * Loco ios export: Xcode Strings (legacy)
3 | * Project: CoreUI
4 | * Locale: de, German
5 | * Tagged: ios
6 | * Exported by: Baptiste Griva
7 | * Exported at: Tue, 30 Sep 2025 09:48:07 +0200
8 | */
9 |
10 | /* loco:679b18c9e56503c64e0f47b2 */
11 | "applicationSourceCode" = "Siehe Quellcode";
12 |
13 | /* loco:679b16a81b0e3541200e1672 */
14 | "authorizeTracking" = "Verfolgung genehmigen";
15 |
16 | /* loco:679b17a8f70dbaf41b0c3c92 */
17 | "trackingManagementDescription" = "Bei Infomaniak sind Ihre Daten niemals eine Währung. Wir verwenden ausschließlich interne Tools, die von uns gehostet und kontrolliert werden, um die Qualität und die Weiterentwicklung unserer Anwendungen zu gewährleisten.\n\nDiese technischen Daten sind vertraulich, werden auf unseren eigenen Servern in der Schweiz gespeichert, sind nur für unsere Entwicklungsteams zugänglich und werden niemals an Dritte weitergegeben. Der Quellcode der Anwendungen kann überprüft werden, wodurch eine vollständige Transparenz gewährleistet wird.";
18 |
19 | /* loco:679b1726759efd28eb0aae82 */
20 | "trackingManagementTitle" = "Verwaltung der Daten";
21 |
22 | /* loco:679b1934489a90910a02ef02 */
23 | "trackingMatomoDescription" = "Matomo ist ein Analysetool, das ausschliesslich von Infomaniak gehostet und verwaltet wird, um zu verstehen, wie die Anwendung genutzt wird.\n\nDurch die Untersuchung dieser Daten kann unser Team die Schnittstelle der Anwendung kontinuierlich verbessern.";
24 |
25 | /* loco:679b19a71cbd373edb0fcc92 */
26 | "trackingMatomoTitle" = "Matomo";
27 |
28 | /* loco:679b19effce81c25230ef922 */
29 | "trackingSentryDescription" = "Sentry ist ein Tool, das ausschliesslich von Infomaniak gehostet und verwaltet wird, um die Stabilität der Anwendung in Echtzeit zu überwachen und unseren Entwicklern automatisch alle technischen Fehler zu melden.\n\nAnhand dieser Daten kann unser Team die Anwendung schnell korrigieren und optimieren, was zu einem besseren Nutzererlebnis für Sie führt.";
30 |
31 | /* loco:679b1a63d5844c9d0d041fb2 */
32 | "trackingSentryTitle" = "Sentry";
33 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/sentry-short.imageset/sentry.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Assets/Assets+InfomaniakCore.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | // swiftlint:disable all
20 | // swift-format-ignore-file
21 | // swiftformat:disable all
22 |
23 | #if os(macOS)
24 | import AppKit
25 | #elseif os(iOS)
26 | import UIKit
27 | #elseif os(tvOS) || os(watchOS)
28 | import UIKit
29 | #endif
30 | // swiftlint:disable superfluous_disable_command file_length implicit_return
31 |
32 | // MARK: - Asset Catalogs
33 |
34 | // swiftlint:disable identifier_name line_length nesting type_body_length type_name
35 | public enum InfomaniakCoreAsset {
36 | public static let backgroundCardView = InfomaniakCoreColor(name: "backgroundCardView")
37 | public static let backgroundCardViewSelected = InfomaniakCoreColor(name: "backgroundCardViewSelected")
38 | public static let titleColor = InfomaniakCoreColor(name: "titleColor")
39 | public static let primaryTextColor = InfomaniakCoreColor(name: "primaryTextColor")
40 | public static let infomaniakColor = InfomaniakCoreColor(name: "infomaniakColor")
41 | }
42 |
43 | // swiftlint:enable identifier_name line_length nesting type_body_length type_name
44 | // swiftlint:enable all
45 | // swiftformat:enable all
46 |
47 | // MARK: - Implementation Details
48 |
49 | public struct InfomaniakCoreColor {
50 | public fileprivate(set) var name: String
51 |
52 | public var color: UIColor {
53 | return UIColor(named: name, in: Bundle.module, compatibleWith: nil)!
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/Buttons/IKSquareButtonStyle.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 |
21 | @available(iOS 15.0, *)
22 | public struct IKSquareButtonStyle: ButtonStyle {
23 | @Environment(\.ikButtonLoading) private var isLoading: Bool
24 |
25 | public func makeBody(configuration: Configuration) -> some View {
26 | configuration.label
27 | .labelStyle(.ikLabel)
28 | .modifier(IKButtonOpacityAnimationModifier(isPressed: configuration.isPressed))
29 | .modifier(IKButtonLoadingModifier(isFilled: true))
30 | .frame(width: IKButtonHeight.extraLarge, height: IKButtonHeight.extraLarge)
31 | .modifier(IKButtonFilledModifier(buttonRole: configuration.role, isProminent: true))
32 | .allowsHitTesting(!isLoading)
33 | }
34 | }
35 |
36 | @available(iOS 15.0, *)
37 | public extension ButtonStyle where Self == IKSquareButtonStyle {
38 | static var ikSquare: IKSquareButtonStyle {
39 | return IKSquareButtonStyle()
40 | }
41 | }
42 |
43 | @available(iOS 15.0, *)
44 | #Preview {
45 | NavigationView {
46 | List {
47 | Section("Standard Button") {
48 | Button {} label: {
49 | Image(systemName: "visionpro")
50 | .iconSize(.medium)
51 | }
52 | }
53 | }
54 | .buttonStyle(.ikSquare)
55 | .navigationTitle("IKSquareButtonStyle")
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/sentry-short.imageset/sentry-dark.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/AvatarColors.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #if canImport(UIKit)
20 | import UIKit
21 |
22 | public extension UIColor {
23 | static let avatarColors = [
24 | UIColor.InfomaniakColors.yellow,
25 | UIColor.InfomaniakColors.coral,
26 | UIColor.InfomaniakColors.grass,
27 | UIColor.InfomaniakColors.fougere,
28 | UIColor.InfomaniakColors.cobalt,
29 | UIColor.InfomaniakColors.jean,
30 | UIColor.InfomaniakColors.tropical,
31 | UIColor.InfomaniakColors.mauve,
32 | UIColor.InfomaniakColors.prince
33 | ]
34 |
35 | class func backgroundColor(from hash: Int, with colors: [UIColor] = UIColor.avatarColors) -> UIColor {
36 | let colorIndex = abs(hash % colors.count)
37 | return colors[colorIndex]
38 | }
39 | }
40 | #endif
41 |
42 | import SwiftUI
43 |
44 | public extension Color {
45 | static let avatarColors = [
46 | Color.InfomaniakColors.yellow,
47 | Color.InfomaniakColors.coral,
48 | Color.InfomaniakColors.grass,
49 | Color.InfomaniakColors.fougere,
50 | Color.InfomaniakColors.cobalt,
51 | Color.InfomaniakColors.jean,
52 | Color.InfomaniakColors.tropical,
53 | Color.InfomaniakColors.mauve,
54 | Color.InfomaniakColors.prince
55 | ]
56 |
57 | static func backgroundColor(from hash: Int, with colors: [Color] = Color.avatarColors) -> Color {
58 | let colorIndex = abs(hash % colors.count)
59 | return colors[colorIndex]
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/CameraPickerView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import PhotosUI
20 | import SwiftUI
21 |
22 | public struct CameraPickerView: UIViewControllerRepresentable {
23 | @Environment(\.dismiss) private var dismiss
24 | @Binding private var selectedImage: UIImage?
25 |
26 | public init(selectedImage: Binding) {
27 | _selectedImage = selectedImage
28 | }
29 |
30 | public func makeUIViewController(context: Context) -> UIImagePickerController {
31 | let imagePicker = UIImagePickerController()
32 | imagePicker.sourceType = .camera
33 | imagePicker.delegate = context.coordinator
34 | return imagePicker
35 | }
36 |
37 | public func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
38 |
39 | public func makeCoordinator() -> Coordinator {
40 | return Coordinator(parent: self)
41 | }
42 |
43 | public class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
44 | private var parent: CameraPickerView
45 |
46 | public init(parent: CameraPickerView) {
47 | self.parent = parent
48 | }
49 |
50 | public func imagePickerController(
51 | _ picker: UIImagePickerController,
52 | didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]
53 | ) {
54 | if let image = info[.originalImage] as? UIImage {
55 | parent.selectedImage = image
56 | }
57 | parent.dismiss()
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/.swiftformat:
--------------------------------------------------------------------------------
1 | --acronyms ID,URL,UUID
2 | --allman false
3 | --assetliterals visual-width
4 | --asynccapturing
5 | --beforemarks
6 | --binarygrouping 4,8
7 | --categorymark "MARK: %c"
8 | --classthreshold 0
9 | --closingparen balanced
10 | --closurevoid remove
11 | --commas always
12 | --conflictmarkers reject
13 | --decimalgrouping 3,6
14 | --elseposition same-line
15 | --emptybraces no-space
16 | --enumnamespaces always
17 | --enumthreshold 0
18 | --exponentcase lowercase
19 | --exponentgrouping disabled
20 | --extensionacl on-extension
21 | --extensionlength 0
22 | --extensionmark "MARK: - %t + %c"
23 | --fractiongrouping disabled
24 | --fragment false
25 | --funcattributes preserve
26 | --generictypes
27 | --groupedextension "MARK: %c"
28 | --guardelse auto
29 | --header ignore
30 | --hexgrouping 4,8
31 | --hexliteralcase uppercase
32 | --ifdef no-indent
33 | --importgrouping alpha
34 | --indent 4
35 | --indentcase false
36 | --indentstrings false
37 | --lifecycle
38 | --lineaftermarks true
39 | --linebreaks lf
40 | --markcategories true
41 | --markextensions always
42 | --marktypes always
43 | --maxwidth 130
44 | --modifierorder
45 | --nevertrailing
46 | --nospaceoperators
47 | --nowrapoperators
48 | --octalgrouping 4,8
49 | --operatorfunc spaced
50 | --organizetypes actor,class,enum,struct
51 | --patternlet inline
52 | --ranges spaced
53 | --redundanttype inferred
54 | --self remove
55 | --selfrequired
56 | --semicolons inline
57 | --shortoptionals always
58 | --smarttabs enabled
59 | --someany true
60 | --stripunusedargs unnamed-only
61 | --structthreshold 0
62 | --tabwidth unspecified
63 | --throwcapturing
64 | --trailingclosures
65 | --trimwhitespace always
66 | --typeattributes preserve
67 | --typeblanklines remove
68 | --typemark "MARK: - %t"
69 | --varattributes preserve
70 | --voidtype void
71 | --wraparguments preserve
72 | --wrapcollections preserve
73 | --wrapconditions preserve
74 | --wrapeffects preserve
75 | --wrapenumcases always
76 | --wrapparameters default
77 | --wrapreturntype preserve
78 | --wrapternary default
79 | --wraptypealiases preserve
80 | --xcodeindentation disabled
81 | --yodaswap always
82 | --disable andOperator,opaqueGenericParameters,preferKeyPath,redundantReturn,strongOutlets,trailingCommas,unusedArguments,wrapMultilineStatementBraces,conditionalAssignment
83 | --enable blankLineAfterImports,blankLinesBetweenImports
84 | --exclude DerivedData,Derived,Tuist,Project.swift,Build,.build,Sources/InfomaniakCoreUIResources/Generated/
85 |
86 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIKit/Extension/Model/InfomaniakUser+Avatar.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import InfomaniakCore
20 | import Nuke
21 | import UIKit
22 |
23 | public extension InfomaniakUser {
24 | /// Can fetch an avatar from any abstract `InfomaniakUser`
25 | func getAvatar(size: CGSize = CGSize(width: 40, height: 40), completion: @MainActor @escaping (UIImage) -> Void) {
26 | let id = self.id
27 | let displayName = self.displayName
28 | let avatar = self.avatar
29 |
30 | Task {
31 | let avatarImage = await getAvatar(id: id, displayName: displayName, avatar: avatar, size: size)
32 | await completion(avatarImage)
33 | }
34 | }
35 |
36 | private func defaultAvatar(id: Int, displayName: String, size: CGSize) -> UIImage {
37 | let backgroundColor = UIColor.backgroundColor(from: id)
38 | return UIImage.getInitialsPlaceholder(with: displayName, size: size, backgroundColor: backgroundColor)
39 | }
40 |
41 | private func getAvatar(id: Int, displayName: String, avatar: String?, size: CGSize) async -> UIImage {
42 | guard let avatarString = avatar,
43 | let url = URL(string: avatarString) else {
44 | return defaultAvatar(id: id, displayName: displayName, size: size)
45 | }
46 |
47 | guard let avatarImage = try? await ImagePipeline.shared.image(for: url) else {
48 | return defaultAvatar(id: id, displayName: displayName, size: size)
49 | }
50 |
51 | return avatarImage
52 | }
53 |
54 | func getAvatar(size: CGSize = CGSize(width: 40, height: 40)) async -> UIImage {
55 | return await getAvatar(id: id, displayName: displayName, avatar: avatar, size: size)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreCommonUI/Security/AppLockHelper.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import LocalAuthentication
20 | import UIKit
21 |
22 | public final class AppLockHelper {
23 | public static let lockAfterOneMinute: TimeInterval = 60
24 |
25 | private var deviceHasBeenLocked = false
26 | private let intervalToLockApp: TimeInterval
27 | private var timeSinceAppEnteredBackground = TimeInterval.zero
28 |
29 | public var isAppLocked: Bool {
30 | let timeHasExpired = timeSinceAppEnteredBackground + intervalToLockApp < Date().timeIntervalSince1970
31 | return isAvailable() && (timeHasExpired || deviceHasBeenLocked)
32 | }
33 |
34 | public init(intervalToLockApp: TimeInterval = AppLockHelper.lockAfterOneMinute) {
35 | self.intervalToLockApp = intervalToLockApp
36 | NotificationCenter.default.addObserver(self,
37 | selector: #selector(deviceDidLock),
38 | name: UIApplication.willResignActiveNotification,
39 | object: nil)
40 | }
41 |
42 | public func isAvailable(_ context: LAContext? = nil) -> Bool {
43 | let currentContext = context ?? LAContext()
44 | return currentContext.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil)
45 | }
46 |
47 | public func setTime() {
48 | timeSinceAppEnteredBackground = Date().timeIntervalSince1970
49 | deviceHasBeenLocked = false
50 | }
51 |
52 | public func evaluatePolicy(reason: String) async throws -> Bool {
53 | let context = LAContext()
54 | guard isAvailable(context) else {
55 | return false
56 | }
57 |
58 | return try await context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason)
59 | }
60 |
61 | @objc private func deviceDidLock() {
62 | deviceHasBeenLocked = true
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Modifiers/SceneLifecycleModifier.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2024 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import InfomaniakCore
20 | import InfomaniakDI
21 | import SwiftUI
22 |
23 | public extension View {
24 | func sceneLifecycle(willEnterForeground: (() -> Void)? = nil, didEnterBackground: (() -> Void)? = nil) -> some View {
25 | return modifier(SceneLifecycleModifier(willEnterForeground: willEnterForeground, didEnterBackground: didEnterBackground))
26 | }
27 | }
28 |
29 | struct SceneLifecycleModifier: ViewModifier {
30 | @LazyInjectService private var platformDetector: PlatformDetectable
31 |
32 | var willEnterForeground: (() -> Void)?
33 | var didEnterBackground: (() -> Void)?
34 |
35 | func body(content: Content) -> some View {
36 | content
37 | .onAppear {
38 | /*
39 | On iOS/iPadOS, the `UIScene.willEnterForegroundNotification` notification is not posted when
40 | the app is opened for the first time.
41 | */
42 | if !platformDetector.isMac {
43 | willEnterForeground?()
44 | }
45 | }
46 | .onReceive(NotificationCenter.default.publisher(for: UIScene.willEnterForegroundNotification)) { _ in
47 | /*
48 | On iOS/iPadOS:
49 | `scenePhase` changes each time a pop-up is presented.
50 | We have to listen to `UIScene.willEnterForegroundNotification` to increase the `appLaunchCounter`
51 | only when the app enters foreground.
52 |
53 | On macOS:
54 | `scenePhase` stays always active even when the app is on the background.
55 | */
56 | willEnterForeground?()
57 | }
58 | .onReceive(NotificationCenter.default.publisher(for: UIScene.didEnterBackgroundNotification)) { _ in
59 | didEnterBackground?()
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/Buttons/Models/IKButtonTheme.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 |
21 | @available(iOS 15.0, *)
22 | @frozen public struct IKButtonTheme {
23 | public let primary: any ShapeStyle
24 | public let secondary: any ShapeStyle
25 | public let tertiary: any ShapeStyle
26 |
27 | public let disabledPrimary: any ShapeStyle
28 | public let disabledSecondary: any ShapeStyle
29 |
30 | public let error: any ShapeStyle
31 |
32 | public let smallFont: Font
33 | public let mediumFont: Font
34 |
35 | public init(
36 | primary: any ShapeStyle,
37 | secondary: any ShapeStyle,
38 | tertiary: any ShapeStyle,
39 | disabledPrimary: any ShapeStyle,
40 | disabledSecondary: any ShapeStyle,
41 | error: any ShapeStyle,
42 | smallFont: Font,
43 | mediumFont: Font
44 | ) {
45 | self.primary = primary
46 | self.secondary = secondary
47 | self.tertiary = tertiary
48 | self.disabledPrimary = disabledPrimary
49 | self.disabledSecondary = disabledSecondary
50 | self.error = error
51 | self.smallFont = smallFont
52 | self.mediumFont = mediumFont
53 | }
54 | }
55 |
56 | // MARK: - Helpers
57 |
58 | @available(iOS 15.0, *)
59 | extension IKButtonTheme {
60 | func scaledFont(_ controlSize: ControlSize) -> Font {
61 | if controlSize == .small {
62 | return smallFont
63 | } else {
64 | return mediumFont
65 | }
66 | }
67 | }
68 |
69 | // MARK: - Default Theme
70 |
71 | @available(iOS 15.0, *)
72 | extension IKButtonTheme {
73 | static let defaultTheme = IKButtonTheme(
74 | primary: TintShapeStyle.tint,
75 | secondary: Color.white,
76 | tertiary: Color.gray.opacity(0.4),
77 | disabledPrimary: Color.gray,
78 | disabledSecondary: Color.white,
79 | error: Color.red,
80 | smallFont: .callout,
81 | mediumFont: .body
82 | )
83 | }
84 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/sentry-long.imageset/sentry-text.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIKit/UICollectionView/InsetCollectionViewCell.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import UIKit
20 |
21 | open class InsetCollectionViewCell: UICollectionViewCell {
22 | @IBOutlet open weak var topConstraint: NSLayoutConstraint?
23 | @IBOutlet open weak var bottomConstraint: NSLayoutConstraint?
24 | @IBOutlet open weak var contentInsetView: UIView!
25 | @IBOutlet open weak var separator: UIView?
26 |
27 | override open func awakeFromNib() {
28 | super.awakeFromNib()
29 | selectedBackgroundView = UIView()
30 | }
31 |
32 | open func initWithPositionAndShadow(isFirst: Bool = false, isLast: Bool = false, elevation: Double = 0, radius: CGFloat = 6) {
33 | if isLast && isFirst {
34 | separator?.isHidden = true
35 | topConstraint?.constant = 8
36 | bottomConstraint?.constant = 8
37 | contentInsetView.roundCorners(
38 | corners: [.layerMaxXMaxYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMinXMinYCorner],
39 | radius: radius
40 | )
41 | } else if isFirst {
42 | separator?.isHidden = false
43 | topConstraint?.constant = 8
44 | bottomConstraint?.constant = 0
45 | contentInsetView.roundCorners(corners: [.layerMaxXMinYCorner, .layerMinXMinYCorner], radius: radius)
46 | } else if isLast {
47 | separator?.isHidden = true
48 | topConstraint?.constant = 0
49 | bottomConstraint?.constant = 8
50 | contentInsetView.roundCorners(corners: [.layerMaxXMaxYCorner, .layerMinXMaxYCorner], radius: radius)
51 | } else {
52 | separator?.isHidden = false
53 | topConstraint?.constant = 0
54 | bottomConstraint?.constant = 0
55 | contentInsetView.roundCorners(
56 | corners: [.layerMaxXMaxYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMinXMinYCorner],
57 | radius: 0
58 | )
59 | }
60 | contentInsetView.addShadow(elevation: elevation)
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/AlertView/AskForReviewView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import DesignSystem
20 | import InfomaniakCore
21 | import InfomaniakCoreCommonUI
22 | import InfomaniakCoreUIResources
23 | import InfomaniakDI
24 | import SwiftUI
25 |
26 | public struct AskForReviewView: View {
27 | private let appName: String
28 | private let feedbackURL: String
29 | private let onLike: () async throws -> Void
30 | private let onDislike: (URL) -> Void
31 | private let reviewManager: ReviewManageable
32 |
33 | public init(
34 | appName: String,
35 | feedbackURL: String,
36 | reviewManager: ReviewManageable,
37 | onLike: @escaping () async throws -> Void,
38 | onDislike: @escaping (URL) -> Void
39 | ) {
40 | self.appName = appName
41 | self.feedbackURL = feedbackURL
42 | self.reviewManager = reviewManager
43 | self.onLike = onLike
44 | self.onDislike = onDislike
45 | }
46 |
47 | public var body: some View {
48 | VStack(alignment: .leading, spacing: 0) {
49 | Text(CoreUILocalizable.reviewAlertTitle(appName))
50 | .padding(.bottom, IKPadding.large)
51 |
52 | ModalButtonsView(
53 | primaryButtonTitle: CoreUILocalizable.buttonYes,
54 | secondaryButtonTitle: CoreUILocalizable.buttonNo,
55 | primaryButtonAction: {
56 | try await onLike()
57 | reviewManager.requestReview()
58 | },
59 | secondaryButtonAction: {
60 | if let userReportURL = URL(string: feedbackURL) {
61 | onDislike(userReportURL)
62 | }
63 | }
64 | )
65 | }
66 | }
67 | }
68 |
69 | #Preview {
70 | AskForReviewView(
71 | appName: "InfomaniakCoreUI ",
72 | feedbackURL: "https://infomaniak.com",
73 | reviewManager: ReviewManager(
74 | userDefaults: UserDefaults.standard,
75 | openingBeforeFirstReview: 1,
76 | openingBeforeNextReviews: 2
77 | ),
78 | onLike: {},
79 | onDislike: { _ in
80 | }
81 | )
82 | }
83 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreUIKit/TitleSizeAdjustingNavigationController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #if os(macOS)
20 | import AppKit
21 | #elseif os(iOS)
22 | import UIKit
23 | #elseif os(tvOS) || os(watchOS)
24 | import UIKit
25 | #endif
26 |
27 | /// A `UINavigationController` that adjusts the font size of its large title labels to fit its content
28 | open class TitleSizeAdjustingNavigationController: UINavigationController {
29 | var minimumScaleFactor: CGFloat = 0.5
30 |
31 | #if !os(tvOS)
32 | override public func viewDidLayoutSubviews() {
33 | guard navigationBar.prefersLargeTitles else { return }
34 |
35 | updateLargeTitleLabels()
36 | }
37 | #endif
38 |
39 | private func updateLargeTitleLabels() {
40 | for largeTitleLabel in largeTitleLabels() {
41 | largeTitleLabel.adjustsFontSizeToFitWidth = true
42 | largeTitleLabel.minimumScaleFactor = minimumScaleFactor
43 | }
44 | }
45 |
46 | private func largeTitleLabels() -> [UILabel] {
47 | let subviews = recursiveSubviews(of: navigationBar)
48 | let labels = subviews.compactMap { $0 as? UILabel }
49 | let titles = viewControllers.compactMap { $0.navigationItem.title } + viewControllers.compactMap { $0.title }
50 | let titleLabels = labels.filter {
51 | if let text = $0.text, titles.contains(text) {
52 | return true
53 | }
54 | return false
55 | }
56 | // 'large' title labels are identified by comparing font size
57 | let titleLabelFontSizes = titleLabels.map { $0.font.pointSize }
58 | let largeTitleLabelFontSize = titleLabelFontSizes.max()
59 | let largeTitleLabels = titleLabels.filter { $0.font.pointSize == largeTitleLabelFontSize }
60 | return largeTitleLabels
61 | }
62 |
63 | private func recursiveSubviews(of view: UIView) -> [UIView] {
64 | var result = [UIView]()
65 | for subview in view.subviews {
66 | result.append(subview)
67 | result.append(contentsOf: recursiveSubviews(of: subview))
68 | }
69 | return result
70 | }
71 |
72 | override open var childForStatusBarStyle: UIViewController? {
73 | return topViewController
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/Discovery/DiscoveryPresenter.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import DesignSystem
20 | import SwiftUI
21 |
22 | public extension View {
23 | func discoveryPresenter(
24 | isPresented: Binding,
25 | topPadding: CGFloat = IKPadding.large,
26 | bottomPadding: CGFloat = IKPadding.medium,
27 | alertBackgroundColor: Color,
28 | sheetBackgroundColor: Color,
29 | @ViewBuilder modalContent: @escaping () -> ModalContent
30 | ) -> some View {
31 | modifier(DiscoveryPresenter(
32 | isPresented: isPresented,
33 | topPadding: topPadding,
34 | bottomPadding: bottomPadding,
35 | alertBackgroundColor: alertBackgroundColor,
36 | sheetBackgroundColor: sheetBackgroundColor,
37 | modalContent: modalContent
38 | ))
39 | }
40 | }
41 |
42 | struct DiscoveryPresenter: ViewModifier {
43 | @Environment(\.isCompactWindow) private var isCompactWindow
44 |
45 | @Binding var isPresented: Bool
46 |
47 | let topPadding: CGFloat
48 | let bottomPadding: CGFloat
49 | let alertBackgroundColor: Color
50 | let sheetBackgroundColor: Color
51 | @ViewBuilder let modalContent: ModalContent
52 |
53 | func body(content: Content) -> some View {
54 | content
55 | .sheet(isPresented: Binding(get: { isCompactWindow && isPresented }, set: { isPresented = $0 })) {
56 | if #available(iOS 16.0, *) {
57 | modalContent.modifier(SelfSizingPanelViewModifier(topPadding: topPadding, bottomPadding: bottomPadding))
58 | .background(sheetBackgroundColor)
59 | } else {
60 | modalContent.modifier(SelfSizingPanelBackportViewModifier(
61 | topPadding: topPadding,
62 | bottomPadding: bottomPadding
63 | ))
64 | .background(sheetBackgroundColor)
65 | }
66 | }
67 | .customAlert(
68 | isPresented: Binding(get: { !isCompactWindow && isPresented }, set: { isPresented = $0 }),
69 | backgroundColor: alertBackgroundColor
70 | ) {
71 | modalContent
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/TrackerDetailsView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2025 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import DesignSystem
20 | import InfomaniakCore
21 | import InfomaniakCoreSwiftUI
22 | import InfomaniakDI
23 | import SwiftUI
24 |
25 | @available(iOS 15.0, *)
26 | struct TrackerDetailsView: View {
27 | @Environment(\.dismiss) private var dismiss
28 |
29 | @AppStorage private var dataValue: Bool
30 |
31 | private let backgroundColor: Color
32 | private let tracker: Tracker
33 |
34 | init(tracker: Tracker, appStorageKey: String, backgroundColor: Color) {
35 | self.tracker = tracker
36 | _dataValue = AppStorage(wrappedValue: true, appStorageKey)
37 | self.backgroundColor = backgroundColor
38 | }
39 |
40 | var body: some View {
41 | NavigationView {
42 | ScrollView {
43 | VStack(alignment: .leading, spacing: 0) {
44 | tracker.logoLong
45 | .padding(.vertical, value: .medium)
46 | .frame(maxWidth: .infinity)
47 |
48 | Text(LocalizedStringKey(tracker.description), bundle: .module)
49 | .font(.body)
50 | .multilineTextAlignment(.leading)
51 | .padding(IKPadding.medium)
52 |
53 | Toggle(isOn: $dataValue) {
54 | Text("authorizeTracking", bundle: .module)
55 | .font(.body)
56 | }
57 | .tint(.accentColor)
58 | .padding(value: .medium)
59 | }
60 | }
61 | .background(backgroundColor)
62 | .navigationBarTitle(Text(tracker.title, bundle: .module), displayMode: .inline)
63 | .toolbar {
64 | ToolbarItem(placement: .navigationBarLeading) {
65 | Button {
66 | dismiss()
67 | } label: {
68 | Image(systemName: "xmark")
69 | .resizable()
70 | .scaledToFit()
71 | }
72 | }
73 | }
74 | }
75 | }
76 | }
77 |
78 | @available(iOS 15.0, *)
79 | #Preview {
80 | TrackerDetailsView(
81 | tracker: Tracker.matomo,
82 | appStorageKey: "matomoKey",
83 | backgroundColor: .white
84 | )
85 | }
86 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Helpers/FileType/FileType.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2024 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 | import UniformTypeIdentifiers
21 |
22 | @available(iOS 14.0, *)
23 | public extension UTType {
24 | static let pages = UTType("com.apple.iwork.pages.sffpages")!
25 | static let wordDoc = UTType("com.microsoft.word.doc")!
26 | static let wordDocm = UTType(mimeType: "application/vnd.ms-word")!
27 | static let wordDocx = UTType("org.openxmlformats.wordprocessingml.document")!
28 | static let onlyOffice = UTType("org.oasis-open.opendocument.text")!
29 |
30 | static let ics = UTType(mimeType: "application/ics")!
31 | }
32 |
33 | @available(iOS 14.0, *)
34 | public extension FileType {
35 | static let archive = FileType(asset: "file-archive", types: [.archive])
36 | static let audio = FileType(asset: "file-audio", types: [.audio])
37 | static let code = FileType(asset: "file-code", types: [.sourceCode, .html, .json, .xml])
38 | static let doc = FileType(asset: "file-doc", types: [.text, .pages, .onlyOffice, .wordDoc, .wordDocm, .wordDocx])
39 | static let font = FileType(asset: "file-font", types: [.font])
40 | static let grid = FileType(asset: "file-grid", types: [.spreadsheet])
41 | static let ics = FileType(asset: "file-ics", types: [.calendarEvent, .ics])
42 | static let image = FileType(asset: "file-img", types: [.image])
43 | static let pdf = FileType(asset: "file-pdf", types: [.pdf])
44 | static let point = FileType(asset: "file-point", types: [.presentation])
45 | static let vCard = FileType(asset: "file-vcard", types: [.vCard])
46 | static let video = FileType(asset: "file-video", types: [.video, .movie])
47 |
48 | static let unknown = FileType(asset: "file-unknown", types: [])
49 | }
50 |
51 | @available(iOS 14.0, *)
52 | public struct FileType: Sendable {
53 | public let image: Image
54 | public let color: Color
55 | public let types: [UTType]
56 |
57 | public init(image: Image, color: Color, types: [UTType]) {
58 | self.image = image
59 | self.color = color
60 | self.types = types
61 | }
62 |
63 | private init(asset: String, types: [UTType]) {
64 | self.init(image: Image(asset, bundle: .module), color: Color("\(asset)-color", bundle: .module), types: types)
65 | }
66 |
67 | public func conforms(to type: UTType) -> Bool {
68 | return types.contains { conformingType in
69 | type.conforms(to: conformingType)
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/WebView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import SwiftUI
20 | import UIKit
21 | import WebKit
22 |
23 | public struct WebView: UIViewRepresentable {
24 | public typealias UIViewType = WKWebView
25 |
26 | let initialURL: URL
27 | var onPageLoaded: ((URL) -> Void)?
28 | var shouldNavigateToPage: ((WKWebView, WKNavigationAction, @escaping (WKNavigationActionPolicy) -> Void) -> Void)?
29 |
30 | public init(
31 | initialURL: URL,
32 | onPageLoaded: ((URL) -> Void)? = nil,
33 | shouldNavigateToPage: ((WKWebView, WKNavigationAction, @escaping (WKNavigationActionPolicy) -> Void) -> Void)? = nil
34 | ) {
35 | self.initialURL = initialURL
36 | self.onPageLoaded = onPageLoaded
37 | self.shouldNavigateToPage = shouldNavigateToPage
38 | }
39 |
40 | public class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate {
41 | var parent: WebView
42 |
43 | init(_ parent: WebView) {
44 | self.parent = parent
45 | }
46 |
47 | public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation) {
48 | guard let pageURL = webView.url else { return }
49 | parent.onPageLoaded?(pageURL)
50 | }
51 |
52 | public func webView(
53 | _ webView: WKWebView,
54 | decidePolicyFor navigationAction: WKNavigationAction,
55 | decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
56 | ) {
57 | guard let shouldNavigateToPage = parent.shouldNavigateToPage else {
58 | decisionHandler(.allow)
59 | return
60 | }
61 | shouldNavigateToPage(webView, navigationAction, decisionHandler)
62 | }
63 | }
64 |
65 | public func makeCoordinator() -> Coordinator {
66 | Coordinator(self)
67 | }
68 |
69 | public func makeUIView(context: Context) -> WKWebView {
70 | let webView = WKWebView()
71 | webView.navigationDelegate = context.coordinator
72 | webView.uiDelegate = context.coordinator
73 | webView.scrollView.bounces = false
74 | webView.scrollView.bouncesZoom = false
75 | webView.scrollView.showsVerticalScrollIndicator = false
76 | webView.scrollView.showsHorizontalScrollIndicator = true
77 | webView.scrollView.alwaysBounceVertical = false
78 | webView.scrollView.alwaysBounceHorizontal = false
79 |
80 | webView.load(URLRequest(url: initialURL))
81 | return webView
82 | }
83 |
84 | public func updateUIView(_ uiView: WKWebView, context: Context) {
85 | // needed for UIViewRepresentable
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Components/Buttons/ModalButtonsView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2023 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import DesignSystem
20 | import InfomaniakCoreCommonUI
21 | import InfomaniakCoreUIResources
22 | import OSLog
23 | import SwiftUI
24 |
25 | public struct ModalButtonsView: View {
26 | @Environment(\.dismiss) private var dismiss
27 |
28 | @State private var isButtonLoading = false
29 |
30 | private let primaryButtonTitle: String
31 | private var secondaryButtonTitle: String?
32 | private var primaryButtonEnabled = true
33 | private let primaryButtonAction: () async throws -> Void
34 | private var secondaryButtonAction: (() -> Void)?
35 | private var primaryButtonRole: ButtonRole?
36 |
37 | public init(
38 | primaryButtonTitle: String,
39 | secondaryButtonTitle: String? = CoreUILocalizable.buttonCancel,
40 | primaryButtonEnabled: Bool = true,
41 | primaryButtonAction: @escaping () async throws -> Void,
42 | secondaryButtonAction: (() -> Void)? = nil,
43 | primaryButtonRole: ButtonRole? = nil
44 | ) {
45 | self.primaryButtonTitle = primaryButtonTitle
46 | self.primaryButtonEnabled = primaryButtonEnabled
47 | self.secondaryButtonTitle = secondaryButtonTitle
48 | self.primaryButtonAction = primaryButtonAction
49 | self.secondaryButtonAction = secondaryButtonAction
50 | self.primaryButtonRole = primaryButtonRole
51 | }
52 |
53 | public var body: some View {
54 | HStack(spacing: IKPadding.micro) {
55 | if let secondaryButtonTitle {
56 | Button {
57 | secondaryButtonAction?()
58 | dismiss()
59 | } label: {
60 | Text(secondaryButtonTitle)
61 | }
62 | .buttonStyle(.ikBorderless)
63 | .keyboardShortcut(.cancelAction)
64 | }
65 |
66 | Button(primaryButtonTitle, role: primaryButtonRole) {
67 | Task {
68 | isButtonLoading = true
69 | do {
70 | try await primaryButtonAction()
71 | dismiss()
72 | } catch {
73 | Logger.view.warning("\(error)")
74 | }
75 | isButtonLoading = false
76 | }
77 | }
78 | .buttonStyle(.ikBorderedProminent)
79 | .disabled(!primaryButtonEnabled)
80 | .ikButtonLoading(isButtonLoading)
81 | .keyboardShortcut(.defaultAction)
82 | }
83 | .frame(maxWidth: .infinity, alignment: .trailing)
84 | }
85 | }
86 |
87 | #Preview {
88 | ModalButtonsView(primaryButtonTitle: "Save", secondaryButtonTitle: nil) { /* Preview */ }
89 | }
90 |
--------------------------------------------------------------------------------
/Sources/InfomaniakPrivacyManagement/Resources/Assets.xcassets/sentry-long.imageset/sentry-text-dark.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.7
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "InfomaniakCoreUI",
8 | defaultLocalization: "en",
9 | platforms: [
10 | .iOS(.v15)
11 | ],
12 | products: [
13 | .library(
14 | name: "InfomaniakCoreCommonUI",
15 | targets: ["InfomaniakCoreCommonUI"]
16 | ),
17 | .library(
18 | name: "InfomaniakCoreUIKit",
19 | targets: ["InfomaniakCoreUIKit"]
20 | ),
21 | .library(
22 | name: "InfomaniakCoreSwiftUI",
23 | targets: ["InfomaniakCoreSwiftUI"]
24 | ),
25 | .library(
26 | name: "InfomaniakPrivacyManagement",
27 | targets: ["InfomaniakPrivacyManagement"]
28 | ),
29 | .library(
30 | name: "InfomaniakCoreUIResources",
31 | targets: ["InfomaniakCoreUIResources"]
32 | ),
33 | .library(
34 | name: "DesignSystem",
35 | targets: ["DesignSystem"]
36 | )
37 | ],
38 | dependencies: [
39 | .package(url: "https://github.com/Infomaniak/ios-core", .upToNextMajor(from: "18.0.0")),
40 | .package(url: "https://github.com/Infomaniak/SnackBar.swift", .upToNextMajor(from: "1.2.0")),
41 | .package(url: "https://github.com/kean/Nuke", .upToNextMajor(from: "12.8.0")),
42 | .package(url: "https://github.com/matomo-org/matomo-sdk-ios", .upToNextMajor(from: "7.5.2")),
43 | .package(url: "https://github.com/shaps80/SwiftUIBackports", .upToNextMajor(from: "1.15.1")),
44 | .package(url: "https://github.com/siteline/SwiftUI-Introspect", .upToNextMajor(from: "26.0.0")),
45 | .package(url: "https://github.com/airbnb/lottie-spm", .upToNextMajor(from: "4.5.2"))
46 | ],
47 | targets: [
48 | .target(
49 | name: "InfomaniakCoreCommonUI",
50 | dependencies: [
51 | "Nuke",
52 | .product(name: "MatomoTracker", package: "matomo-sdk-ios"),
53 | .product(name: "InfomaniakCore", package: "ios-core"),
54 | .product(name: "SnackBar", package: "SnackBar.swift")
55 | ]
56 | ),
57 | .target(
58 | name: "InfomaniakCoreUIKit",
59 | dependencies: ["InfomaniakCoreCommonUI"]
60 | ),
61 | .target(
62 | name: "InfomaniakCoreSwiftUI",
63 | dependencies: [
64 | "SwiftUIBackports",
65 | "DesignSystem",
66 | "InfomaniakCoreUIResources",
67 | "InfomaniakCoreCommonUI",
68 | .product(name: "Lottie", package: "lottie-spm"),
69 | .product(name: "InfomaniakCore", package: "ios-core"),
70 | .product(name: "SwiftUIIntrospect-Dynamic", package: "SwiftUI-Introspect")
71 | ]
72 | ),
73 | .target(
74 | name: "InfomaniakPrivacyManagement",
75 | dependencies: [
76 | "DesignSystem",
77 | "InfomaniakCoreSwiftUI"
78 | ]
79 | ),
80 | .target(
81 | name: "InfomaniakCoreUIResources"
82 | ),
83 | .target(
84 | name: "DesignSystem"
85 | ),
86 | .testTarget(
87 | name: "InfomaniakCoreUITests",
88 | dependencies: ["InfomaniakCoreCommonUI", "InfomaniakCoreUIKit", "InfomaniakCoreSwiftUI"]
89 | )
90 | ]
91 | )
92 |
--------------------------------------------------------------------------------
/Sources/InfomaniakCoreSwiftUI/Modifiers/FloatingPanelHelper.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Infomaniak Core UI - iOS
3 | Copyright (C) 2024 Infomaniak Network SA
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | import DesignSystem
20 | import InfomaniakCore
21 | import InfomaniakDI
22 | import SwiftUI
23 | import SwiftUIBackports
24 | import SwiftUIIntrospect
25 |
26 | @available(iOS 15, *)
27 | public extension View {
28 | func floatingPanel(
29 | isPresented: Binding,
30 | title: String? = nil,
31 | closeButtonHidden: Bool = false,
32 | backgroundColor: Color,
33 | topPadding: CGFloat = IKPadding.large,
34 | bottomPadding: CGFloat = IKPadding.medium,
35 | @ViewBuilder content: @escaping () -> Content
36 | ) -> some View {
37 | sheet(isPresented: isPresented) {
38 | if #available(iOS 16.0, *) {
39 | content().modifier(SelfSizingPanelViewModifier(
40 | title: title,
41 | closeButtonHidden: closeButtonHidden,
42 | topPadding: topPadding,
43 | bottomPadding: bottomPadding
44 | ))
45 | .background(backgroundColor)
46 | } else {
47 | content().modifier(SelfSizingPanelBackportViewModifier(
48 | title: title,
49 | closeButtonHidden: closeButtonHidden,
50 | topPadding: topPadding,
51 | bottomPadding: bottomPadding
52 | ))
53 | .background(backgroundColor)
54 | }
55 | }
56 | }
57 |
58 | func floatingPanel(
59 | item: Binding- ,
60 | backgroundColor: Color,
61 | title: String? = nil,
62 | closeButtonHidden: Bool = false,
63 | topPadding: CGFloat = IKPadding.large,
64 | bottomPadding: CGFloat = IKPadding.medium,
65 | @ViewBuilder content: @escaping (Item) -> Content
66 | ) -> some View {
67 | sheet(item: item) { item in
68 | if #available(iOS 16.0, *) {
69 | content(item)
70 | .modifier(SelfSizingPanelViewModifier(
71 | title: title,
72 | closeButtonHidden: closeButtonHidden,
73 | topPadding: topPadding,
74 | bottomPadding: bottomPadding
75 | ))
76 | .background(backgroundColor)
77 | } else {
78 | content(item)
79 | .modifier(SelfSizingPanelBackportViewModifier(
80 | title: title,
81 | closeButtonHidden: closeButtonHidden,
82 | topPadding: topPadding,
83 | bottomPadding: bottomPadding
84 | ))
85 | .background(backgroundColor)
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------