├── .github
├── FUNDING.yml
└── workflows
│ ├── testflight.yaml
│ └── tests.yaml
├── .gitignore
├── Bark.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ ├── Bark.xcscheme
│ ├── NotificationContentExtension.xcscheme
│ └── NotificationServiceExtension.xcscheme
├── Bark.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── Bark
├── AppDelegate.swift
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ └── bark.png
│ ├── Colors
│ │ ├── Contents.json
│ │ ├── background.colorset
│ │ │ └── Contents.json
│ │ ├── background_seconday.colorset
│ │ │ └── Contents.json
│ │ ├── black.colorset
│ │ │ └── Contents.json
│ │ ├── blue_base.colorset
│ │ │ └── Contents.json
│ │ ├── blue_darken1.colorset
│ │ │ └── Contents.json
│ │ ├── blue_darken5.colorset
│ │ │ └── Contents.json
│ │ ├── darkText_primary.colorset
│ │ │ └── Contents.json
│ │ ├── darkText_secondary.colorset
│ │ │ └── Contents.json
│ │ ├── grey_base.colorset
│ │ │ └── Contents.json
│ │ ├── grey_darken1.colorset
│ │ │ └── Contents.json
│ │ ├── grey_darken2.colorset
│ │ │ └── Contents.json
│ │ ├── grey_darken3.colorset
│ │ │ └── Contents.json
│ │ ├── grey_darken4.colorset
│ │ │ └── Contents.json
│ │ ├── grey_lighten1.colorset
│ │ │ └── Contents.json
│ │ ├── grey_lighten2.colorset
│ │ │ └── Contents.json
│ │ ├── grey_lighten3.colorset
│ │ │ └── Contents.json
│ │ ├── grey_lighten4.colorset
│ │ │ └── Contents.json
│ │ ├── grey_lighten5.colorset
│ │ │ └── Contents.json
│ │ ├── lightBlue_darken3.colorset
│ │ │ └── Contents.json
│ │ ├── notification_copy_color.colorset
│ │ │ └── Contents.json
│ │ └── white.colorset
│ │ │ └── Contents.json
│ ├── Contents.json
│ ├── back.imageset
│ │ ├── Contents.json
│ │ ├── back@2x.png
│ │ └── back@3x.png
│ ├── baseline_check_circle_outline_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_check_circle_outline_black_24pt_1x.png
│ │ ├── baseline_check_circle_outline_black_24pt_2x.png
│ │ └── baseline_check_circle_outline_black_24pt_3x.png
│ ├── baseline_close_white_48pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_close_white_48pt_1x.png
│ │ ├── baseline_close_white_48pt_2x.png
│ │ └── baseline_close_white_48pt_3x.png
│ ├── baseline_delete_outline_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_delete_outline_black_24pt_1x.png
│ │ ├── baseline_delete_outline_black_24pt_2x.png
│ │ └── baseline_delete_outline_black_24pt_3x.png
│ ├── baseline_file_copy_white_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_file_copy_white_24pt_1x.png
│ │ ├── baseline_file_copy_white_24pt_2x.png
│ │ └── baseline_file_copy_white_24pt_3x.png
│ ├── baseline_filter_drama_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_filter_drama_black_24pt_1x.png
│ │ ├── baseline_filter_drama_black_24pt_2x.png
│ │ └── baseline_filter_drama_black_24pt_3x.png
│ ├── baseline_folder_open_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_folder_open_black_24pt_1x.png
│ │ ├── baseline_folder_open_black_24pt_2x.png
│ │ └── baseline_folder_open_black_24pt_3x.png
│ ├── baseline_gite_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_gite_black_24pt_1x.png
│ │ ├── baseline_gite_black_24pt_2x.png
│ │ └── baseline_gite_black_24pt_3x.png
│ ├── baseline_http_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_http_black_24pt_1x.png
│ │ ├── baseline_http_black_24pt_2x.png
│ │ └── baseline_http_black_24pt_3x.png
│ ├── baseline_https_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_https_black_24pt_1x.png
│ │ ├── baseline_https_black_24pt_2x.png
│ │ └── baseline_https_black_24pt_3x.png
│ ├── baseline_keyboard_arrow_down_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_keyboard_arrow_down_black_24pt_1x.png
│ │ ├── baseline_keyboard_arrow_down_black_24pt_2x.png
│ │ └── baseline_keyboard_arrow_down_black_24pt_3x.png
│ ├── baseline_manage_accounts_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_manage_accounts_black_24pt_1x.png
│ │ ├── baseline_manage_accounts_black_24pt_2x.png
│ │ └── baseline_manage_accounts_black_24pt_3x.png
│ ├── baseline_qr_code_scanner_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_qr_code_scanner_black_24pt_1x.png
│ │ ├── baseline_qr_code_scanner_black_24pt_2x.png
│ │ └── baseline_qr_code_scanner_black_24pt_3x.png
│ ├── baseline_radio_button_unchecked_black_24pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_radio_button_unchecked_black_24pt_1x.png
│ │ ├── baseline_radio_button_unchecked_black_24pt_2x.png
│ │ └── baseline_radio_button_unchecked_black_24pt_3x.png
│ ├── baseline_remove_black_20pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_remove_black_20pt_1x.png
│ │ ├── baseline_remove_black_20pt_2x.png
│ │ └── baseline_remove_black_20pt_3x.png
│ ├── baseline_wifi_black_20pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_wifi_black_20pt_1x.png
│ │ ├── baseline_wifi_black_20pt_2x.png
│ │ └── baseline_wifi_black_20pt_3x.png
│ ├── baseline_wifi_off_black_20pt.imageset
│ │ ├── Contents.json
│ │ ├── baseline_wifi_off_black_20pt_1x.png
│ │ ├── baseline_wifi_off_black_20pt_2x.png
│ │ └── baseline_wifi_off_black_20pt_3x.png
│ ├── copyTest.imageset
│ │ ├── Contents.json
│ │ ├── preview_copy@3x.png
│ │ └── preview_copy_dark@3x.png
│ ├── criticalAlert.imageset
│ │ ├── Contents.json
│ │ ├── IMG_8023.jpg
│ │ └── IMG_8024.jpg
│ ├── group.imageset
│ │ ├── Contents.json
│ │ ├── preview_group_dark@3x.png
│ │ └── preview_group_default@3x.png
│ ├── group_collapse.imageset
│ │ ├── Contents.json
│ │ ├── folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz242 (2).png
│ │ └── folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz242 (3).png
│ ├── group_expand.imageset
│ │ ├── Contents.json
│ │ ├── folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz24 1.png
│ │ └── folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.png
│ ├── icon.imageset
│ │ ├── Contents.json
│ │ ├── preview_icon_dark@3x.png
│ │ └── preview_icon_default@3x.png
│ ├── keyboard_arrow_right_symbol.symbolset
│ │ ├── Contents.json
│ │ └── keyboard_arrow_right_keyboard_arrow_right_symbol.svg
│ ├── music_note-music_note_symbol.symbolset
│ │ ├── Contents.json
│ │ └── music_note-music_note_symbol.svg
│ ├── offline.imageset
│ │ ├── Contents.json
│ │ └── offline@3x.png
│ ├── online.imageset
│ │ ├── Contents.json
│ │ └── online@3X.png
│ └── warning.imageset
│ │ ├── Contents.json
│ │ └── warning@3x.png
├── Bark.entitlements
├── Base.lproj
│ └── LaunchScreen.storyboard
├── Info.plist
├── Intents
│ ├── OptionsProvider.swift
│ ├── PushResponse.swift
│ ├── PushToCurrentIntent.swift
│ └── PushToOtherIntent.swift
└── Localizable.xcstrings
├── BarkTests
├── BarkTests.swift
├── HomeViewModelTests.swift
├── Info.plist
└── MessageDeleteTimeRangeTest.swift
├── Common
├── ArchiveSettingManager.swift
├── ArchiveSettingRelay.swift
├── BKColor.swift
├── BarkSettings.swift
├── Client.swift
├── CryptoSettingManager.swift
├── CryptoSettingRelay.swift
├── Date+Extension.swift
├── Defines.swift
├── Error+Extension.swift
├── GroupMuteSettingManager.swift
├── MJRefresh+Rx.swift
├── Moya
│ ├── BarkApi.swift
│ ├── BarkTargetType.swift
│ └── Observable+Extension.swift
├── NSLocalizedString+Extension.swift
├── Operators.swift
├── RealmConfiguration.swift
├── Reusable.swift
├── ServerManager.swift
├── SharedDefines.swift
├── String+Extension.swift
├── UIColor+Extension.swift
├── UIFont+Extension.swift
└── ViewModelType.swift
├── Controller
├── BarkNavigationController.swift
├── BarkSFSafariViewController.swift
├── BarkSplitViewController.swift
├── BarkTabBarController.swift
├── BaseViewController.swift
├── CrashReportViewController.swift
├── CryptoSettingController.swift
├── CryptoSettingViewModel.swift
├── HomeViewController.swift
├── HomeViewModel.swift
├── MessageListViewController.swift
├── MessageListViewModel.swift
├── MessageSettingsViewController.swift
├── MessageSettingsViewModel.swift
├── NewServerViewController.swift
├── NewServerViewModel.swift
├── QRScannerViewController.swift
├── SectionViewController-iPad.swift
├── SectionViewModel-iPad.swift
├── ServerListViewController.swift
├── ServerListViewModel.swift
├── SoundsViewController.swift
└── SoundsViewModel.swift
├── Gemfile
├── LICENSE
├── Model
├── Algorithm.swift
├── Message.swift
├── MessageDeleteTimeRange.swift
├── MessageItemModel.swift
├── MessageSection.swift
├── Object+Dictionary.swift
└── PreviewModel.swift
├── NotificationServiceExtension
├── Info.plist
├── NotificationService.swift
├── NotificationServiceExtension.entitlements
└── Processor
│ ├── ArchiveProcessor.swift
│ ├── AutoCopyProcessor.swift
│ ├── BadgeProcessor.swift
│ ├── CallProcessor.swift
│ ├── CiphertextProcessor.swift
│ ├── IconProcessor.swift
│ ├── ImageDownloader.swift
│ ├── ImageProcessor.swift
│ ├── LevelProcessor.swift
│ ├── MuteProcessor.swift
│ └── NotificationContentProcessor.swift
├── Podfile
├── Podfile.lock
├── README.md
├── README.zh.md
├── Sounds
├── alarm.caf
├── anticipate.caf
├── bell.caf
├── birdsong.caf
├── bloom.caf
├── calypso.caf
├── chime.caf
├── choo.caf
├── descent.caf
├── electronic.caf
├── fanfare.caf
├── glass.caf
├── gotosleep.caf
├── healthnotification.caf
├── horn.caf
├── ladder.caf
├── mailsent.caf
├── minuet.caf
├── multiwayinvitation.caf
├── newmail.caf
├── newsflash.caf
├── noir.caf
├── paymentsuccess.caf
├── shake.caf
├── sherwoodforest.caf
├── silence.caf
├── spell.caf
├── suspense.caf
├── telegraph.caf
├── tiptoes.caf
├── typewriters.caf
└── update.caf
├── View
├── AddSoundCell.swift
├── ArchiveSettingCell.swift
├── ArchiveSettingCellViewModel.swift
├── BKButton.swift
├── BKDropDownCell.swift
├── BKDropDownCell.xib
├── BKLabel.swift
├── BaseTableViewCell.swift
├── BorderTextField.swift
├── DonateCell.swift
├── DropBoxView.swift
├── GesturePassTextView.swift
├── GradientButton.swift
├── HUD.swift
├── LabelCell.swift
├── MessageList
│ ├── CustomTapTextView.swift
│ ├── MessageGroupHeaderView.swift
│ ├── MessageGroupMoreView.swift
│ ├── MessageItemView.swift
│ ├── MessageTableViewCell.swift
│ └── ShowLessAndClearView.swift
├── MessageSettingFooter.swift
├── MutableTextCell.swift
├── MutableTextCellViewModel.swift
├── PreviewCardCell.swift
├── PreviewCardCellViewModel.swift
├── ServerListTableViewCell.swift
├── ServerListTableViewCellViewModel.swift
├── SettingSectionHeader.swift
├── SoundCell.swift
├── SoundCellViewModel.swift
├── SpacerCell.swift
├── TextCell.swift
├── UINavigationItem+Extension.swift
└── iCloudStatusCell.swift
├── docs
├── .nojekyll
├── CNAME
├── README.md
├── _coverpage.md
├── _media
│ ├── Icon.png
│ ├── environment.png
│ ├── example.jpg
│ └── shortcuts_cn.png
├── _navbar.md
├── _sidebar.md
├── batch.md
├── build.md
├── cert.md
├── deploy.md
├── en-us
│ ├── README.md
│ ├── _coverpage.md
│ ├── _sidebar.md
│ ├── batch.md
│ ├── build.md
│ ├── cert.md
│ ├── deploy.md
│ ├── encryption.md
│ ├── faq.md
│ ├── privacy.md
│ └── tutorial.md
├── encryption.md
├── faq.md
├── index.html
├── privacy.md
└── tutorial.md
├── fastlane
├── Appfile
├── Fastfile
└── Matchfile
└── notificationContentExtension
├── Base.lproj
└── MainInterface.storyboard
├── Info.plist
├── NotificationContentExtension.entitlements
└── NotificationViewController.swift
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [Finb]
4 |
--------------------------------------------------------------------------------
/.github/workflows/testflight.yaml:
--------------------------------------------------------------------------------
1 | name: Deploy to App Store
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | storeVersionNumber:
7 | description: 'Store Version Number'
8 | required: true
9 | default: ""
10 | buildNumber:
11 | description: 'Build Number'
12 | required: true
13 | default: ""
14 |
15 | jobs:
16 | deploy:
17 | runs-on: macos-latest
18 |
19 | steps:
20 | - name: Checkout
21 | uses: actions/checkout@v4
22 |
23 | - name: Select Xcode Version
24 | uses: maxim-lobanov/setup-xcode@v1
25 | with:
26 | xcode-version: '16.1'
27 |
28 | - name: Setup ruby
29 | uses: ruby/setup-ruby@v1
30 | with:
31 | ruby-version: 2.7.2
32 | bundler-cache: true
33 |
34 | - uses: actions/cache@v4
35 | id: pods-cache
36 | with:
37 | path: Pods
38 | key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
39 | restore-keys: |
40 | ${{ runner.os }}-pods-
41 |
42 | - name: Install Pods
43 | run: pod install
44 |
45 | - name: Build & Distribute to App Store
46 | run: |
47 | export LC_ALL=en_US.UTF-8
48 | export LANG=en_US.UTF-8
49 | bundle exec fastlane beta store_version_number:${{ github.event.inputs.storeVersionNumber }} build_number:${{ github.event.inputs.buildNumber }}
50 | env:
51 | APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
52 | APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}
53 | BARK_KEY: ${{ secrets.BARK_KEY }}
54 | MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }}
55 | MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
56 |
57 | - name: Archive artifacts
58 | uses: actions/upload-artifact@v4
59 | with:
60 | name: dSYM
61 | path: Bark.app.dSYM.zip
62 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yaml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | tests:
13 | runs-on: macos-latest
14 |
15 | steps:
16 | - name: Checkout
17 | uses: actions/checkout@v4
18 |
19 | - name: Select Xcode Version
20 | uses: maxim-lobanov/setup-xcode@v1
21 | with:
22 | xcode-version: 'latest-stable'
23 |
24 | - name: Setup ruby
25 | uses: ruby/setup-ruby@v1
26 | with:
27 | ruby-version: 2.7.2
28 | bundler-cache: true
29 |
30 | - uses: actions/cache@v4
31 | id: pods-cache
32 | with:
33 | path: Pods
34 | key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
35 | restore-keys: |
36 | ${{ runner.os }}-pods-
37 |
38 | - name: Install Pods
39 | run: pod install
40 |
41 | - name: Run Tests
42 | run: |
43 | export LC_ALL=en_US.UTF-8
44 | export LANG=en_US.UTF-8
45 | bundle exec fastlane tests
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode*v*
2 | *.pbxuser
3 | *.xccheckout
4 | #*.xcbkptlist
5 | #*.xcscheme
6 | #*.xcworkspacedata
7 | *.xcuserstate
8 | build/
9 | Pods/
10 | .DS_Store
11 | ._.*
12 | xcuserdata
13 |
--------------------------------------------------------------------------------
/Bark.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Bark.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Bark.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "bark.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/AppIcon.appiconset/bark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/AppIcon.appiconset/bark.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/background.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "245",
9 | "green" : "245",
10 | "red" : "245"
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",
27 | "green" : "0",
28 | "red" : "0"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/background_seconday.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "255",
9 | "green" : "255",
10 | "red" : "255"
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" : "22",
27 | "green" : "22",
28 | "red" : "22"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/black.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.000",
9 | "green" : "0.000",
10 | "red" : "0.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" : "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 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/blue_base.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "243",
9 | "green" : "150",
10 | "red" : "33"
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" : "243",
27 | "green" : "150",
28 | "red" : "33"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/blue_darken1.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "229",
9 | "green" : "136",
10 | "red" : "30"
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" : "245",
27 | "green" : "165",
28 | "red" : "66"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/blue_darken5.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "216",
9 | "green" : "46",
10 | "red" : "34"
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" : "233",
27 | "green" : "44",
28 | "red" : "70"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/darkText_primary.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "0.870",
8 | "blue" : "255",
9 | "green" : "255",
10 | "red" : "255"
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" : "0.870",
26 | "blue" : "0",
27 | "green" : "0",
28 | "red" : "0"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/darkText_secondary.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "0.540",
8 | "blue" : "255",
9 | "green" : "255",
10 | "red" : "255"
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" : "0.540",
26 | "blue" : "0",
27 | "green" : "0",
28 | "red" : "0"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/grey_base.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "158",
9 | "green" : "158",
10 | "red" : "158"
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" : "97",
27 | "green" : "97",
28 | "red" : "97"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/grey_darken1.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "117",
9 | "green" : "117",
10 | "red" : "117"
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" : "189",
27 | "green" : "189",
28 | "red" : "189"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/grey_darken2.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "97",
9 | "green" : "97",
10 | "red" : "97"
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" : "224",
27 | "green" : "224",
28 | "red" : "224"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/grey_darken3.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "66",
9 | "green" : "66",
10 | "red" : "66"
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" : "238",
27 | "green" : "238",
28 | "red" : "238"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/grey_darken4.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "33",
9 | "green" : "33",
10 | "red" : "33"
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" : "245",
27 | "green" : "245",
28 | "red" : "245"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/grey_lighten1.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "189",
9 | "green" : "189",
10 | "red" : "189"
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" : "117",
27 | "green" : "117",
28 | "red" : "117"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/grey_lighten2.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "214",
9 | "green" : "214",
10 | "red" : "214"
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" : "92",
27 | "green" : "92",
28 | "red" : "92"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/grey_lighten3.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "238",
9 | "green" : "238",
10 | "red" : "238"
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" : "66",
27 | "green" : "66",
28 | "red" : "66"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/grey_lighten4.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "245",
9 | "green" : "245",
10 | "red" : "245"
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" : "33",
27 | "green" : "33",
28 | "red" : "33"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/grey_lighten5.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "250",
9 | "green" : "250",
10 | "red" : "250"
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" : "28",
27 | "green" : "28",
28 | "red" : "28"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/lightBlue_darken3.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "189",
9 | "green" : "119",
10 | "red" : "2"
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" : "250",
27 | "green" : "212",
28 | "red" : "129"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/notification_copy_color.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.000",
9 | "green" : "0.000",
10 | "red" : "0.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" : "1.000",
27 | "green" : "1.000",
28 | "red" : "1.000"
29 | }
30 | },
31 | "idiom" : "universal"
32 | },
33 | {
34 | "color" : {
35 | "color-space" : "srgb",
36 | "components" : {
37 | "alpha" : "1.000",
38 | "blue" : "0.000",
39 | "green" : "0.000",
40 | "red" : "0.000"
41 | }
42 | },
43 | "idiom" : "iphone"
44 | },
45 | {
46 | "appearances" : [
47 | {
48 | "appearance" : "luminosity",
49 | "value" : "dark"
50 | }
51 | ],
52 | "color" : {
53 | "color-space" : "srgb",
54 | "components" : {
55 | "alpha" : "1.000",
56 | "blue" : "1.000",
57 | "green" : "1.000",
58 | "red" : "1.000"
59 | }
60 | },
61 | "idiom" : "iphone"
62 | },
63 | {
64 | "color" : {
65 | "color-space" : "srgb",
66 | "components" : {
67 | "alpha" : "1.000",
68 | "blue" : "0.000",
69 | "green" : "0.000",
70 | "red" : "0.000"
71 | }
72 | },
73 | "idiom" : "ipad"
74 | },
75 | {
76 | "appearances" : [
77 | {
78 | "appearance" : "luminosity",
79 | "value" : "dark"
80 | }
81 | ],
82 | "color" : {
83 | "color-space" : "srgb",
84 | "components" : {
85 | "alpha" : "1.000",
86 | "blue" : "1.000",
87 | "green" : "1.000",
88 | "red" : "1.000"
89 | }
90 | },
91 | "idiom" : "ipad"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Colors/white.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" : "0.000",
27 | "green" : "0.000",
28 | "red" : "0.000"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/back.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "back@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "back@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/back.imageset/back@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/back.imageset/back@2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/back.imageset/back@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/back.imageset/back@3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_check_circle_outline_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_check_circle_outline_black_24pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_check_circle_outline_black_24pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_check_circle_outline_black_24pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_check_circle_outline_black_24pt.imageset/baseline_check_circle_outline_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_check_circle_outline_black_24pt.imageset/baseline_check_circle_outline_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_check_circle_outline_black_24pt.imageset/baseline_check_circle_outline_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_check_circle_outline_black_24pt.imageset/baseline_check_circle_outline_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_check_circle_outline_black_24pt.imageset/baseline_check_circle_outline_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_check_circle_outline_black_24pt.imageset/baseline_check_circle_outline_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_close_white_48pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_close_white_48pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_close_white_48pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_close_white_48pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_close_white_48pt.imageset/baseline_close_white_48pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_close_white_48pt.imageset/baseline_close_white_48pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_close_white_48pt.imageset/baseline_close_white_48pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_close_white_48pt.imageset/baseline_close_white_48pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_close_white_48pt.imageset/baseline_close_white_48pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_close_white_48pt.imageset/baseline_close_white_48pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_delete_outline_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_delete_outline_black_24pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_delete_outline_black_24pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_delete_outline_black_24pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_delete_outline_black_24pt.imageset/baseline_delete_outline_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_delete_outline_black_24pt.imageset/baseline_delete_outline_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_delete_outline_black_24pt.imageset/baseline_delete_outline_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_delete_outline_black_24pt.imageset/baseline_delete_outline_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_delete_outline_black_24pt.imageset/baseline_delete_outline_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_delete_outline_black_24pt.imageset/baseline_delete_outline_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_file_copy_white_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "baseline_file_copy_white_24pt_1x.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "baseline_file_copy_white_24pt_2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "baseline_file_copy_white_24pt_3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_file_copy_white_24pt.imageset/baseline_file_copy_white_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_file_copy_white_24pt.imageset/baseline_file_copy_white_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_file_copy_white_24pt.imageset/baseline_file_copy_white_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_file_copy_white_24pt.imageset/baseline_file_copy_white_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_file_copy_white_24pt.imageset/baseline_file_copy_white_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_file_copy_white_24pt.imageset/baseline_file_copy_white_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_filter_drama_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_filter_drama_black_24pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_filter_drama_black_24pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_filter_drama_black_24pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_filter_drama_black_24pt.imageset/baseline_filter_drama_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_filter_drama_black_24pt.imageset/baseline_filter_drama_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_filter_drama_black_24pt.imageset/baseline_filter_drama_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_filter_drama_black_24pt.imageset/baseline_filter_drama_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_filter_drama_black_24pt.imageset/baseline_filter_drama_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_filter_drama_black_24pt.imageset/baseline_filter_drama_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_folder_open_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_folder_open_black_24pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_folder_open_black_24pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_folder_open_black_24pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_folder_open_black_24pt.imageset/baseline_folder_open_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_folder_open_black_24pt.imageset/baseline_folder_open_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_folder_open_black_24pt.imageset/baseline_folder_open_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_folder_open_black_24pt.imageset/baseline_folder_open_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_folder_open_black_24pt.imageset/baseline_folder_open_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_folder_open_black_24pt.imageset/baseline_folder_open_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_gite_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_gite_black_24pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_gite_black_24pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_gite_black_24pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_gite_black_24pt.imageset/baseline_gite_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_gite_black_24pt.imageset/baseline_gite_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_gite_black_24pt.imageset/baseline_gite_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_gite_black_24pt.imageset/baseline_gite_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_gite_black_24pt.imageset/baseline_gite_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_gite_black_24pt.imageset/baseline_gite_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_http_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "baseline_http_black_24pt_1x.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "baseline_http_black_24pt_2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "baseline_http_black_24pt_3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_http_black_24pt.imageset/baseline_http_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_http_black_24pt.imageset/baseline_http_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_http_black_24pt.imageset/baseline_http_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_http_black_24pt.imageset/baseline_http_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_http_black_24pt.imageset/baseline_http_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_http_black_24pt.imageset/baseline_http_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_https_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "baseline_https_black_24pt_1x.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "baseline_https_black_24pt_2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "baseline_https_black_24pt_3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_https_black_24pt.imageset/baseline_https_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_https_black_24pt.imageset/baseline_https_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_https_black_24pt.imageset/baseline_https_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_https_black_24pt.imageset/baseline_https_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_https_black_24pt.imageset/baseline_https_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_https_black_24pt.imageset/baseline_https_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_keyboard_arrow_down_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_keyboard_arrow_down_black_24pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_keyboard_arrow_down_black_24pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_keyboard_arrow_down_black_24pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_keyboard_arrow_down_black_24pt.imageset/baseline_keyboard_arrow_down_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_keyboard_arrow_down_black_24pt.imageset/baseline_keyboard_arrow_down_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_keyboard_arrow_down_black_24pt.imageset/baseline_keyboard_arrow_down_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_keyboard_arrow_down_black_24pt.imageset/baseline_keyboard_arrow_down_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_keyboard_arrow_down_black_24pt.imageset/baseline_keyboard_arrow_down_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_keyboard_arrow_down_black_24pt.imageset/baseline_keyboard_arrow_down_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_manage_accounts_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_manage_accounts_black_24pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_manage_accounts_black_24pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_manage_accounts_black_24pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_manage_accounts_black_24pt.imageset/baseline_manage_accounts_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_manage_accounts_black_24pt.imageset/baseline_manage_accounts_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_manage_accounts_black_24pt.imageset/baseline_manage_accounts_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_manage_accounts_black_24pt.imageset/baseline_manage_accounts_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_manage_accounts_black_24pt.imageset/baseline_manage_accounts_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_manage_accounts_black_24pt.imageset/baseline_manage_accounts_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_qr_code_scanner_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_qr_code_scanner_black_24pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_qr_code_scanner_black_24pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_qr_code_scanner_black_24pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_qr_code_scanner_black_24pt.imageset/baseline_qr_code_scanner_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_qr_code_scanner_black_24pt.imageset/baseline_qr_code_scanner_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_qr_code_scanner_black_24pt.imageset/baseline_qr_code_scanner_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_qr_code_scanner_black_24pt.imageset/baseline_qr_code_scanner_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_qr_code_scanner_black_24pt.imageset/baseline_qr_code_scanner_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_qr_code_scanner_black_24pt.imageset/baseline_qr_code_scanner_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_radio_button_unchecked_black_24pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_radio_button_unchecked_black_24pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_radio_button_unchecked_black_24pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_radio_button_unchecked_black_24pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_radio_button_unchecked_black_24pt.imageset/baseline_radio_button_unchecked_black_24pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_radio_button_unchecked_black_24pt.imageset/baseline_radio_button_unchecked_black_24pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_radio_button_unchecked_black_24pt.imageset/baseline_radio_button_unchecked_black_24pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_radio_button_unchecked_black_24pt.imageset/baseline_radio_button_unchecked_black_24pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_radio_button_unchecked_black_24pt.imageset/baseline_radio_button_unchecked_black_24pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_radio_button_unchecked_black_24pt.imageset/baseline_radio_button_unchecked_black_24pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_remove_black_20pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_remove_black_20pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_remove_black_20pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_remove_black_20pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_remove_black_20pt.imageset/baseline_remove_black_20pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_remove_black_20pt.imageset/baseline_remove_black_20pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_remove_black_20pt.imageset/baseline_remove_black_20pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_remove_black_20pt.imageset/baseline_remove_black_20pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_remove_black_20pt.imageset/baseline_remove_black_20pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_remove_black_20pt.imageset/baseline_remove_black_20pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_wifi_black_20pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_wifi_black_20pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_wifi_black_20pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_wifi_black_20pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_wifi_black_20pt.imageset/baseline_wifi_black_20pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_wifi_black_20pt.imageset/baseline_wifi_black_20pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_wifi_black_20pt.imageset/baseline_wifi_black_20pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_wifi_black_20pt.imageset/baseline_wifi_black_20pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_wifi_black_20pt.imageset/baseline_wifi_black_20pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_wifi_black_20pt.imageset/baseline_wifi_black_20pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_wifi_off_black_20pt.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "baseline_wifi_off_black_20pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "baseline_wifi_off_black_20pt_2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "baseline_wifi_off_black_20pt_3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | },
23 | "properties" : {
24 | "template-rendering-intent" : "template"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_wifi_off_black_20pt.imageset/baseline_wifi_off_black_20pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_wifi_off_black_20pt.imageset/baseline_wifi_off_black_20pt_1x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_wifi_off_black_20pt.imageset/baseline_wifi_off_black_20pt_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_wifi_off_black_20pt.imageset/baseline_wifi_off_black_20pt_2x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/baseline_wifi_off_black_20pt.imageset/baseline_wifi_off_black_20pt_3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/baseline_wifi_off_black_20pt.imageset/baseline_wifi_off_black_20pt_3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/copyTest.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "idiom" : "universal",
15 | "scale" : "1x"
16 | },
17 | {
18 | "idiom" : "universal",
19 | "scale" : "2x"
20 | },
21 | {
22 | "appearances" : [
23 | {
24 | "appearance" : "luminosity",
25 | "value" : "dark"
26 | }
27 | ],
28 | "idiom" : "universal",
29 | "scale" : "2x"
30 | },
31 | {
32 | "filename" : "preview_copy@3x.png",
33 | "idiom" : "universal",
34 | "scale" : "3x"
35 | },
36 | {
37 | "appearances" : [
38 | {
39 | "appearance" : "luminosity",
40 | "value" : "dark"
41 | }
42 | ],
43 | "filename" : "preview_copy_dark@3x.png",
44 | "idiom" : "universal",
45 | "scale" : "3x"
46 | }
47 | ],
48 | "info" : {
49 | "author" : "xcode",
50 | "version" : 1
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/copyTest.imageset/preview_copy@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/copyTest.imageset/preview_copy@3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/copyTest.imageset/preview_copy_dark@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/copyTest.imageset/preview_copy_dark@3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/criticalAlert.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "idiom" : "universal",
15 | "scale" : "1x"
16 | },
17 | {
18 | "idiom" : "universal",
19 | "scale" : "2x"
20 | },
21 | {
22 | "appearances" : [
23 | {
24 | "appearance" : "luminosity",
25 | "value" : "dark"
26 | }
27 | ],
28 | "idiom" : "universal",
29 | "scale" : "2x"
30 | },
31 | {
32 | "filename" : "IMG_8023.jpg",
33 | "idiom" : "universal",
34 | "scale" : "3x"
35 | },
36 | {
37 | "appearances" : [
38 | {
39 | "appearance" : "luminosity",
40 | "value" : "dark"
41 | }
42 | ],
43 | "filename" : "IMG_8024.jpg",
44 | "idiom" : "universal",
45 | "scale" : "3x"
46 | }
47 | ],
48 | "info" : {
49 | "author" : "xcode",
50 | "version" : 1
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/criticalAlert.imageset/IMG_8023.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/criticalAlert.imageset/IMG_8023.jpg
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/criticalAlert.imageset/IMG_8024.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/criticalAlert.imageset/IMG_8024.jpg
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/group.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "idiom" : "universal",
15 | "scale" : "1x"
16 | },
17 | {
18 | "idiom" : "universal",
19 | "scale" : "2x"
20 | },
21 | {
22 | "appearances" : [
23 | {
24 | "appearance" : "luminosity",
25 | "value" : "dark"
26 | }
27 | ],
28 | "idiom" : "universal",
29 | "scale" : "2x"
30 | },
31 | {
32 | "filename" : "preview_group_default@3x.png",
33 | "idiom" : "universal",
34 | "scale" : "3x"
35 | },
36 | {
37 | "appearances" : [
38 | {
39 | "appearance" : "luminosity",
40 | "value" : "dark"
41 | }
42 | ],
43 | "filename" : "preview_group_dark@3x.png",
44 | "idiom" : "universal",
45 | "scale" : "3x"
46 | }
47 | ],
48 | "info" : {
49 | "author" : "xcode",
50 | "version" : 1
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/group.imageset/preview_group_dark@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/group.imageset/preview_group_dark@3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/group.imageset/preview_group_default@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/group.imageset/preview_group_default@3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/group_collapse.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "filename" : "folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz242 (3).png",
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "filename" : "folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz242 (2).png",
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/group_collapse.imageset/folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz242 (2).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/group_collapse.imageset/folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz242 (2).png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/group_collapse.imageset/folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz242 (3).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/group_collapse.imageset/folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz242 (3).png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/group_expand.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "filename" : "folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz24 1.png",
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "filename" : "folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.png",
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/group_expand.imageset/folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz24 1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/group_expand.imageset/folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz24 1.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/group_expand.imageset/folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/group_expand.imageset/folder_code_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "idiom" : "universal",
15 | "scale" : "1x"
16 | },
17 | {
18 | "idiom" : "universal",
19 | "scale" : "2x"
20 | },
21 | {
22 | "appearances" : [
23 | {
24 | "appearance" : "luminosity",
25 | "value" : "dark"
26 | }
27 | ],
28 | "idiom" : "universal",
29 | "scale" : "2x"
30 | },
31 | {
32 | "filename" : "preview_icon_default@3x.png",
33 | "idiom" : "universal",
34 | "scale" : "3x"
35 | },
36 | {
37 | "appearances" : [
38 | {
39 | "appearance" : "luminosity",
40 | "value" : "dark"
41 | }
42 | ],
43 | "filename" : "preview_icon_dark@3x.png",
44 | "idiom" : "universal",
45 | "scale" : "3x"
46 | }
47 | ],
48 | "info" : {
49 | "author" : "xcode",
50 | "version" : 1
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/icon.imageset/preview_icon_dark@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/icon.imageset/preview_icon_dark@3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/icon.imageset/preview_icon_default@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/icon.imageset/preview_icon_default@3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/keyboard_arrow_right_symbol.symbolset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "symbols" : [
7 | {
8 | "filename" : "keyboard_arrow_right_keyboard_arrow_right_symbol.svg",
9 | "idiom" : "universal"
10 | }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/music_note-music_note_symbol.symbolset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | },
6 | "symbols" : [
7 | {
8 | "filename" : "music_note-music_note_symbol.svg",
9 | "idiom" : "universal"
10 | }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/offline.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "filename" : "offline@3x.png",
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/offline.imageset/offline@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/offline.imageset/offline@3x.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/online.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "filename" : "online@3X.png",
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/online.imageset/online@3X.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/online.imageset/online@3X.png
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/warning.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "filename" : "warning@3x.png",
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Bark/Assets.xcassets/warning.imageset/warning@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Bark/Assets.xcassets/warning.imageset/warning@3x.png
--------------------------------------------------------------------------------
/Bark/Bark.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | aps-environment
6 | development
7 | com.apple.developer.usernotifications.communication
8 |
9 | com.apple.developer.usernotifications.critical-alerts
10 |
11 | com.apple.developer.usernotifications.time-sensitive
12 |
13 | com.apple.security.application-groups
14 |
15 | group.bark
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Bark/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Bark/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPhotoLibraryAddUsageDescription
6 | Save the image to the photo library
7 | CFBundleURLTypes
8 |
9 |
10 | CFBundleURLSchemes
11 |
12 | bark
13 |
14 | CFBundleURLName
15 | me.fin.bark
16 |
17 |
18 | CFBundleDevelopmentRegion
19 | $(DEVELOPMENT_LANGUAGE)
20 | CFBundleDisplayName
21 | Bark
22 | CFBundleExecutable
23 | $(EXECUTABLE_NAME)
24 | CFBundleIdentifier
25 | $(PRODUCT_BUNDLE_IDENTIFIER)
26 | CFBundleInfoDictionaryVersion
27 | 6.0
28 | CFBundleName
29 | $(PRODUCT_NAME)
30 | CFBundlePackageType
31 | APPL
32 | CFBundleShortVersionString
33 | $(MARKETING_VERSION)
34 | CFBundleVersion
35 | $(CURRENT_PROJECT_VERSION)
36 | GitHub Run Id
37 | 0
38 | LSRequiresIPhoneOS
39 |
40 | NSAppTransportSecurity
41 |
42 | NSAllowsArbitraryLoads
43 |
44 |
45 | NSCameraUsageDescription
46 | We are using the camera to scan a QR code
47 | NSUserActivityTypes
48 |
49 | INSendMessageIntent
50 | INStartCallIntent
51 |
52 | UIBackgroundModes
53 |
54 | remote-notification
55 |
56 | UILaunchStoryboardName
57 | LaunchScreen
58 | UIRequiredDeviceCapabilities
59 |
60 | armv7
61 |
62 | UISupportedInterfaceOrientations
63 |
64 | UIInterfaceOrientationPortrait
65 |
66 | UISupportedInterfaceOrientations~ipad
67 |
68 | UIInterfaceOrientationPortrait
69 | UIInterfaceOrientationPortraitUpsideDown
70 | UIInterfaceOrientationLandscapeLeft
71 | UIInterfaceOrientationLandscapeRight
72 |
73 | UIViewControllerBasedStatusBarAppearance
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/Bark/Intents/OptionsProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OptionsProvider.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2/21/25.
6 | // Copyright © 2025 Fin. All rights reserved.
7 | //
8 | import AppIntents
9 |
10 | @available(iOS 16, *)
11 | struct ServerAddressOptionsProvider: DynamicOptionsProvider {
12 | func results() async throws -> [String] {
13 | return ServerManager.shared.servers.map { server in
14 | return server.address + "/" + server.key
15 | }
16 | }
17 |
18 | func defaultResult() async -> String? {
19 | return ServerManager.shared.currentServer.address + "/" + ServerManager.shared.currentServer.key
20 | }
21 | }
22 |
23 | @available(iOS 16, *)
24 | struct SoundOptionsProvider: DynamicOptionsProvider {
25 | func results() async throws -> [String] {
26 | var customSounds: [String] = []
27 | if let soundsDirectoryUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark")?.appendingPathComponent("Library/Sounds").path {
28 | customSounds = getSounds(urls: getFilesInDirectory(directory: soundsDirectoryUrl, suffix: "caf"))
29 | }
30 | let defaultSounds = getSounds(urls: Bundle.main.urls(forResourcesWithExtension: "caf", subdirectory: nil) ?? [])
31 |
32 | return customSounds + defaultSounds
33 | }
34 |
35 | func getSounds(urls: [URL]) -> [String] {
36 | let urls = urls.sorted { u1, u2 -> Bool in
37 | u1.lastPathComponent.localizedStandardCompare(u2.lastPathComponent) == ComparisonResult.orderedAscending
38 | }
39 | return urls.map { $0.deletingPathExtension().lastPathComponent }
40 | }
41 |
42 | func getFilesInDirectory(directory: String, suffix: String) -> [URL] {
43 | let fileManager = FileManager.default
44 | do {
45 | let files = try fileManager.contentsOfDirectory(atPath: directory)
46 | return files.compactMap { file -> URL? in
47 | if file.hasSuffix(suffix), !file.hasPrefix(kBarkSoundPrefix) {
48 | // 不要包含 kBarkSoundPrefix 开头的,这些是为了 call=1 合成的 30s 长铃声,不算用户上传的
49 | return URL(fileURLWithPath: directory).appendingPathComponent(file)
50 | }
51 | return nil
52 | }
53 | } catch {
54 | return []
55 | }
56 | }
57 | }
58 |
59 | @available(iOS 16, *)
60 | struct VolumeOptionsProvider: DynamicOptionsProvider {
61 | func results() async throws -> [Int] {
62 | return Array(0...10)
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Bark/Intents/PushResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PushResponse.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2/21/25.
6 | // Copyright © 2025 Fin. All rights reserved.
7 | //
8 |
9 | struct PushResponse: Decodable {
10 | let message: String?
11 | let code: Int?
12 | }
13 |
--------------------------------------------------------------------------------
/BarkTests/BarkTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BarkTests.swift
3 | // BarkTests
4 | //
5 | // Created by huangfeng on 2021/6/24.
6 | // Copyright © 2021 Fin. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class BarkTests: XCTestCase {
12 | override func setUpWithError() throws {
13 | // Put setup code here. This method is called before the invocation of each test method in the class.
14 | }
15 |
16 | override func tearDownWithError() throws {
17 | // Put teardown code here. This method is called after the invocation of each test method in the class.
18 | }
19 |
20 | func testExample() throws {
21 | // This is an example of a functional test case.
22 | // Use XCTAssert and related functions to verify your tests produce the correct results.
23 | }
24 |
25 | func testPerformanceExample() throws {
26 | // This is an example of a performance test case.
27 | measure {
28 | // Put the code you want to measure the time of here.
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/BarkTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Common/ArchiveSettingManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ArchiveSettingManager.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/5/29.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ArchiveSettingManager: NSObject {
12 | static let shared = ArchiveSettingManager()
13 | let defaults = UserDefaults(suiteName: "group.bark")
14 | var isArchive: Bool {
15 | get {
16 | return defaults?.value(forKey: "isArchive") as? Bool ?? true
17 | }
18 | set {
19 | defaults?.set(newValue, forKey: "isArchive")
20 | }
21 | }
22 |
23 | override private init() {
24 | super.init()
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Common/ArchiveSettingRelay.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ArchiveSettingRelay.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2023/1/30.
6 | // Copyright © 2023 Fin. All rights reserved.
7 | //
8 |
9 | import RxCocoa
10 | import UIKit
11 | class ArchiveSettingRelay: NSObject {
12 | static let shared = ArchiveSettingRelay()
13 | let isArchiveRelay: BehaviorRelay
14 |
15 | override private init() {
16 | self.isArchiveRelay = BehaviorRelay(value: ArchiveSettingManager.shared.isArchive)
17 | super.init()
18 |
19 | self.isArchiveRelay.subscribe { val in
20 | ArchiveSettingManager.shared.isArchive = val
21 | }.disposed(by: rx.disposeBag)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Common/BKColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BKColor.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2021/10/22.
6 | // Copyright © 2021 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class BKColor: NSObject {
12 |
13 | enum grey {
14 | public static let base = UIColor(named: "grey_base")!
15 | public static let darken1 = UIColor(named: "grey_darken1")!
16 | public static let darken2 = UIColor(named: "grey_darken2")!
17 | public static let darken3 = UIColor(named: "grey_darken3")!
18 | public static let darken4 = UIColor(named: "grey_darken4")!
19 | public static let lighten1 = UIColor(named: "grey_lighten1")!
20 | public static let lighten2 = UIColor(named: "grey_lighten2")!
21 | public static let lighten3 = UIColor(named: "grey_lighten3")!
22 | public static let lighten4 = UIColor(named: "grey_lighten4")!
23 | public static let lighten5 = UIColor(named: "grey_lighten5")!
24 | }
25 |
26 | enum blue {
27 | public static let base = UIColor(named: "blue_base")!
28 | public static let darken1 = UIColor(named: "blue_darken1")!
29 | public static let darken5 = UIColor(named: "blue_darken5")!
30 | }
31 |
32 | enum lightBlue {
33 | public static let darken3 = UIColor(named: "lightBlue_darken3")!
34 | }
35 |
36 | public static let white = UIColor(named: "white")!
37 |
38 | public static let black = UIColor(named: "black")!
39 |
40 | enum background {
41 | public static let primary = UIColor(named: "background")!
42 | public static let secondary = UIColor(named: "background_seconday")!
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Common/BarkSettings.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BarkSettings.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2018/6/25.
6 | // Copyright © 2018 Fin. All rights reserved.
7 | //
8 |
9 | import DefaultsKit
10 | import UIKit
11 |
12 | enum BarkSettingKey: String {
13 | /// 存放key , 1.2.6 版本`之后`不再使用
14 | case key = "me.fin.bark.key"
15 | case servers = "me.fin.bark.servers"
16 |
17 | /// 1.2.6 版本`之前`保存当前 server 的 key,不再使用
18 | case currentServer = "me.fin.bark.servers.current"
19 | /// 1.2.6 版本`之后`用于保存 server 的 id
20 | case currentServerId = "me.fin.bark.servers.currentServerId"
21 |
22 | case selectedViewControllerIndex = "me.fin.bark.selectedViewControllerIndex"
23 | }
24 |
25 | class BarkSettings {
26 | static let shared = BarkSettings()
27 | private init() {}
28 |
29 | subscript(key: String) -> String? {
30 | get {
31 | let storeKey = Key(key)
32 | return Defaults.shared.get(for: storeKey)
33 | }
34 | set {
35 | let storeKey = Key(key)
36 | if let value = newValue {
37 | Defaults.shared.set(value, for: storeKey)
38 | }
39 | else {
40 | Defaults.shared.clear(storeKey)
41 | }
42 | }
43 | }
44 |
45 | subscript(key: BarkSettingKey) -> String? {
46 | get {
47 | return self[key.rawValue]
48 | }
49 | set {
50 | self[key.rawValue] = newValue
51 | }
52 | }
53 |
54 | subscript(key: String) -> T? {
55 | get {
56 | let storeKey = Key(key)
57 | return Defaults.shared.get(for: storeKey)
58 | }
59 | set {
60 | let storeKey = Key(key)
61 | if let value = newValue {
62 | Defaults.shared.set(value, for: storeKey)
63 | }
64 | else {
65 | Defaults.shared.clear(storeKey)
66 | }
67 | }
68 | }
69 |
70 | subscript(key: BarkSettingKey) -> T? {
71 | get {
72 | return self[key.rawValue]
73 | }
74 | set {
75 | self[key.rawValue] = newValue
76 | }
77 | }
78 | }
79 |
80 | let Settings = BarkSettings.shared
81 |
--------------------------------------------------------------------------------
/Common/CryptoSettingManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CryptoSettingManager.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2023/3/2.
6 | // Copyright © 2023 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class CryptoSettingManager: NSObject {
12 | static let shared = CryptoSettingManager()
13 | let defaults = UserDefaults(suiteName: "group.bark")
14 | var fields: CryptoSettingFields? {
15 | get {
16 | guard let data:Data = defaults?.value(forKey: "cryptoSettingFields") as? Data else {
17 | return nil
18 | }
19 | guard let fields = try? JSONDecoder().decode(CryptoSettingFields.self, from: data) else {
20 | return nil
21 | }
22 | return fields
23 | }
24 | set {
25 | guard let newValue = newValue else {
26 | defaults?.removeObject(forKey: "cryptoSettingFields")
27 | return
28 | }
29 | guard let encoded = try? JSONEncoder().encode(newValue) else{
30 | return
31 | }
32 | defaults?.set(encoded, forKey: "cryptoSettingFields")
33 | }
34 | }
35 |
36 | override private init() {
37 | super.init()
38 | }
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/Common/CryptoSettingRelay.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CryptoSettingRelay.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2023/3/7.
6 | // Copyright © 2023 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import RxCocoa
11 |
12 | class CryptoSettingRelay: NSObject {
13 | static let shared = CryptoSettingRelay()
14 | let fields: BehaviorRelay
15 |
16 | override private init() {
17 | self.fields = BehaviorRelay(value: CryptoSettingManager.shared.fields)
18 | super.init()
19 |
20 | self.fields.subscribe { val in
21 | CryptoSettingManager.shared.fields = val
22 | }.disposed(by: rx.disposeBag)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Common/Defines.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Defines.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2018/6/26.
6 | // Copyright © 2018 Fin. All rights reserved.
7 | //
8 |
9 | import RxCocoa
10 | import UIKit
11 |
12 | /// 将代码安全的运行在主线程
13 | func dispatch_sync_safely_main_queue(_ block: () -> ()) {
14 | if Thread.isMainThread {
15 | block()
16 | } else {
17 | DispatchQueue.main.sync {
18 | block()
19 | }
20 | }
21 | }
22 |
23 | extension UIViewController {
24 | func showSnackbar(text: String) {
25 | self.snackbarController?.snackbar.text = text
26 | self.snackbarController?.animate(snackbar: .visible)
27 | self.snackbarController?.animate(snackbar: .hidden, delay: 3)
28 | }
29 | }
30 |
31 | let kNavigationHeight: CGFloat = {
32 | kSafeAreaInsets.top + 44
33 | }()
34 |
35 | let kSafeAreaInsets: UIEdgeInsets = {
36 | UIWindow().safeAreaInsets
37 | }()
38 |
39 | func castOrThrow(_ resultType: T.Type, _ object: Any) throws -> T {
40 | guard let returnValue = object as? T else {
41 | throw RxCocoaError.castingError(object: object, targetType: resultType)
42 | }
43 |
44 | return returnValue
45 | }
46 |
--------------------------------------------------------------------------------
/Common/Error+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Error+Extension.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2023/3/3.
6 | // Copyright © 2023 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension String: @retroactive Error {}
12 |
13 | public enum ApiError: Swift.Error {
14 | case Error(info: String)
15 | case AccountBanned(info: String)
16 | }
17 |
18 | extension Swift.Error {
19 | func rawString() -> String {
20 | if let err = self as? String {
21 | return err
22 | }
23 | guard let err = self as? ApiError else {
24 | return self.localizedDescription
25 | }
26 | switch err {
27 | case .Error(let info):
28 | return info
29 | case .AccountBanned(let info):
30 | return info
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Common/GroupMuteSettingManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GroupMuteSettingManager.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 11/6/24.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | let kGroupMuteSettingKey = "groupMuteSettings"
12 |
13 | /// 保存各分组的静音截止时间,注意 NotificationServiceExtension 和 NotificationContentExtension 是不同进程,不共享单例的(别用单例)
14 | class GroupMuteSettingManager: NSObject {
15 | let defaults = UserDefaults(suiteName: "group.bark")
16 |
17 | var settings: [String: Date] = [:] {
18 | didSet {
19 | defaults?.set(settings, forKey: kGroupMuteSettingKey)
20 | }
21 | }
22 |
23 | override init() {
24 | super.init()
25 | if let settings = defaults?.dictionary(forKey: kGroupMuteSettingKey) as? [String: Date] {
26 | self.settings = settings
27 | }
28 | // 清理过期的设置
29 | for setting in settings {
30 | if setting.value < Date() {
31 | self.settings.removeValue(forKey: setting.key)
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Common/MJRefresh+Rx.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MJRefresh+Rx.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/11/22.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import MJRefresh
11 | import RxCocoa
12 | import RxSwift
13 |
14 | extension Reactive where Base: MJRefreshComponent {
15 | var refresh: ControlEvent {
16 | let source = Observable.create { [weak control = self.base] observer -> Disposable in
17 | MainScheduler.ensureExecutingOnScheduler()
18 | guard let control = control else {
19 | observer.onCompleted()
20 | return Disposables.create()
21 | }
22 | control.refreshingBlock = {
23 | observer.onNext(())
24 | }
25 | return Disposables.create()
26 | }
27 | return ControlEvent(events: source)
28 | }
29 | }
30 |
31 | enum MJRefreshAction {
32 | /// 不做任何事情
33 | case none
34 | /// 开始刷新
35 | case begainRefresh
36 | /// 停止刷新
37 | case endRefresh
38 | /// 开始加载更多
39 | case begainLoadmore
40 | /// 停止加载更多
41 | case endLoadmore
42 | /// 显示无更多数据
43 | case showNomoreData
44 | /// 重置无更多数据
45 | case resetNomoreData
46 | }
47 |
48 | extension Reactive where Base: UIScrollView {
49 | /// 执行的操作类型
50 | var refreshAction: Binder {
51 | return Binder(base) { target, action in
52 |
53 | switch action {
54 | case .begainRefresh:
55 | // 下拉刷新使用 UIRefreshControl
56 | if let control = target.refreshControl {
57 | control.beginRefreshing()
58 | }
59 | case .endRefresh:
60 | if let control = target.refreshControl {
61 | control.endRefreshing()
62 | }
63 | case .begainLoadmore:
64 | if let footer = target.mj_footer {
65 | footer.beginRefreshing()
66 | }
67 | case .endLoadmore:
68 | if let footer = target.mj_footer {
69 | footer.endRefreshing()
70 | }
71 | case .showNomoreData:
72 | if let footer = target.mj_footer {
73 | footer.endRefreshingWithNoMoreData()
74 | }
75 | case .resetNomoreData:
76 | if let footer = target.mj_footer {
77 | footer.resetNoMoreData()
78 | }
79 | case .none:
80 | break
81 | }
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Common/Moya/BarkApi.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BarkApi.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2018/6/25.
6 | // Copyright © 2018 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | enum BarkApi {
12 | case ping(baseURL: String?)
13 | case register(address: String, key: String?, devicetoken: String) // 注册设备
14 | }
15 |
16 | extension BarkApi: BarkTargetType {
17 | var baseURL: URL {
18 | switch self {
19 | case let .ping(urlStr):
20 | if let url = URL(string: urlStr ?? "") {
21 | return url
22 | }
23 | case let .register(address, _, _):
24 | if let url = try? address.asURL() {
25 | return url
26 | }
27 | }
28 | return try! ServerManager.shared.currentServer.address.asURL()
29 | }
30 |
31 | var parameters: [String: Any]? {
32 | switch self {
33 | case let .register(_, key, devicetoken):
34 | var params = ["devicetoken": devicetoken]
35 | if let key = key {
36 | params["key"] = key
37 | }
38 | return params
39 | default:
40 | return nil
41 | }
42 | }
43 |
44 | var path: String {
45 | switch self {
46 | case .ping:
47 | return "/ping"
48 | case .register:
49 | return "/register"
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Common/NSLocalizedString+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSLocalizedString+Extension.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2023/3/3.
6 | // Copyright © 2023 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | func NSLocalizedString(_ key: String) -> String {
12 | return NSLocalizedString(key, comment: "")
13 | }
14 |
--------------------------------------------------------------------------------
/Common/RealmConfiguration.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RealmConfiguration.swift
3 | // NotificationServiceExtension
4 | //
5 | // Created by huangfeng on 2024/5/29.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | @_exported import RealmSwift
10 | import UIKit
11 |
12 | let kRealmDefaultConfiguration = {
13 | let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark")
14 | let fileUrl = groupUrl?.appendingPathComponent("bark.realm")
15 | let config = Realm.Configuration(
16 | fileURL: fileUrl,
17 | schemaVersion: 16,
18 | migrationBlock: { migration, oldSchemaVersion in
19 | switch oldSchemaVersion {
20 | case 0...13:
21 | migration.enumerateObjects(ofType: Message.className()) { oldObject, newObject in
22 | guard let obj = oldObject else {
23 | return
24 | }
25 | guard let isDeleted = obj["isDeleted"] as? Bool else {
26 | return
27 | }
28 | // 旧版软删除的数据,迁移到新版时硬删除掉,新版不再过滤 isDeleted 字段
29 | if isDeleted, let newObject {
30 | migration.delete(newObject)
31 | }
32 | }
33 | default:
34 | break
35 | }
36 | }
37 | )
38 | return config
39 | }()
40 |
--------------------------------------------------------------------------------
/Common/Reusable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Reusable.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/11/17.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import RxCocoa
10 | import RxSwift
11 | import UIKit
12 |
13 | private var prepareForReuseBag: Int8 = 0
14 |
15 | @objc public protocol Reusable: AnyObject {
16 | func prepareForReuse()
17 | }
18 |
19 | extension UITableViewCell: Reusable {}
20 | extension UITableViewHeaderFooterView: Reusable {}
21 | extension UICollectionReusableView: Reusable {}
22 |
23 | extension Reactive where Base: Reusable {
24 | var reuseBag: DisposeBag {
25 | MainScheduler.ensureExecutingOnScheduler()
26 |
27 | if let bag = objc_getAssociatedObject(base, &prepareForReuseBag) as? DisposeBag {
28 | return bag
29 | }
30 |
31 | let bag = DisposeBag()
32 | objc_setAssociatedObject(base, &prepareForReuseBag, bag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
33 |
34 | _ = sentMessage(#selector(Base.prepareForReuse))
35 | .take(until: deallocated)
36 | .subscribe(onNext: { [weak base] _ in
37 | guard let strongBase = base else {
38 | return
39 | }
40 | let newBag = DisposeBag()
41 | objc_setAssociatedObject(strongBase, &prepareForReuseBag, newBag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
42 | })
43 |
44 | return bag
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Common/SharedDefines.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SharedDefines.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2024/7/26.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | let kBarkSoundPrefix = "bark.sounds.30s"
12 |
--------------------------------------------------------------------------------
/Common/String+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+Extension.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2018/6/26.
6 | // Copyright © 2018 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension String {
12 | // 将原始的url编码为合法的url
13 | func urlEncoded() -> String {
14 | let encodeUrlString = self.addingPercentEncoding(withAllowedCharacters:
15 | .urlQueryAllowed)
16 | return encodeUrlString ?? ""
17 | }
18 |
19 | // 将编码后的url转换回原始的url
20 | func urlDecoded() -> String {
21 | return self.removingPercentEncoding ?? ""
22 | }
23 | }
24 |
25 | // MARK: - NSAttributedString
26 |
27 | extension String {
28 | var bold: NSAttributedString {
29 | return NSMutableAttributedString(string: self, attributes: [.font: UIFont.boldSystemFont(ofSize: UIFont.systemFontSize)])
30 | }
31 |
32 | var underline: NSAttributedString {
33 | return NSAttributedString(string: self, attributes: [.underlineStyle: NSUnderlineStyle.single.rawValue])
34 | }
35 |
36 | var strikethrough: NSAttributedString {
37 | return NSAttributedString(string: self, attributes: [.strikethroughStyle: NSNumber(value: NSUnderlineStyle.single.rawValue as Int)])
38 | }
39 |
40 | var italic: NSAttributedString {
41 | return NSMutableAttributedString(string: self, attributes: [.font: UIFont.italicSystemFont(ofSize: UIFont.systemFontSize)])
42 | }
43 |
44 | func colored(with color: UIColor) -> NSAttributedString {
45 | return NSMutableAttributedString(string: self, attributes: [.foregroundColor: color])
46 | }
47 | }
48 |
49 | // MARK: - Format
50 |
51 | extension String {
52 | func format(_ arguments: any CVarArg...) -> String {
53 | return String(format: self, arguments)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Common/UIColor+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+Extension.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2018/6/25.
6 | // Copyright © 2018 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | public convenience init(r255: CGFloat, g255: CGFloat, b255: CGFloat, a255: CGFloat = 255) {
13 | self.init(red: r255/255, green: g255/255, blue: b255/255, alpha: a255/255)
14 | }
15 |
16 | class func image(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage {
17 | UIGraphicsBeginImageContext(size)
18 | let context = UIGraphicsGetCurrentContext()
19 | context?.setFillColor(color.cgColor)
20 | context?.fill(CGRect(origin: CGPoint.zero, size: size))
21 |
22 | let image = UIGraphicsGetImageFromCurrentImageContext()
23 | UIGraphicsEndImageContext()
24 | return image! // context应该不会没get到吧~ 所以直接强解了
25 | }
26 |
27 | var image: UIImage {
28 | return UIColor.image(color: self)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Common/UIFont+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIFont+Extension.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 10/25/24.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIFont {
12 | class func preferredFont(ofSize size: CGFloat, weight: Weight = .regular) -> UIFont {
13 | return UIFontMetrics.default.scaledFont(for: UIFont.systemFont(ofSize: size, weight: weight))
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Common/ViewModelType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewModelType.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/11/17.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import RxSwift
11 |
12 | protocol ViewModelType {
13 | associatedtype Input
14 | associatedtype Output
15 |
16 | func transform(input: Input) -> Output
17 | }
18 |
19 | class ViewModel: NSObject {}
20 |
--------------------------------------------------------------------------------
/Controller/BarkNavigationController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BarkNavigationController.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2018/6/25.
6 | // Copyright © 2018 Fin. All rights reserved.
7 | //
8 |
9 | import Material
10 | import RxSwift
11 | import UIKit
12 |
13 | class BarkNavigationController: UINavigationController {
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 | self.navigationBar.prefersLargeTitles = true
17 | }
18 | }
19 |
20 | class BarkSnackbarController: SnackbarController {
21 | override var childForStatusBarStyle: UIViewController? {
22 | return self.rootViewController
23 | }
24 | }
25 |
26 | enum TabPage: Int {
27 | case unknown = -1
28 | case service = 0
29 | case messageHistory = 1
30 | case settings = 2
31 | }
32 |
33 | class StateStorageTabBarController: UITabBarController, UITabBarControllerDelegate {
34 | // 标记当前显示的页面,再次点击相同的页面时当做页面点击事件。
35 | var currentSelectedIndex: Int = 0
36 |
37 | // 点击当前页面的 tabBarItem , 可以用以点击刷新当前页面等操作
38 | lazy var tabBarItemDidClick: Observable = {
39 | self.rx.didSelect
40 | .flatMapLatest { _ -> Single in
41 | let single = Single.create { single in
42 | if self.currentSelectedIndex == self.selectedIndex {
43 | single(.success(TabPage(rawValue: self.selectedIndex) ?? .unknown))
44 | }
45 | self.currentSelectedIndex = self.selectedIndex
46 | return Disposables.create()
47 | }
48 | return single
49 | }.share()
50 | }()
51 |
52 | var isFirstAppear = true
53 | override func viewWillAppear(_ animated: Bool) {
54 | super.viewWillAppear(animated)
55 | if isFirstAppear {
56 | isFirstAppear = false
57 |
58 | // 开启APP时,默认选择上次打开的页面
59 | if let index: Int = Settings[.selectedViewControllerIndex] {
60 | self.selectedIndex = index
61 | self.currentSelectedIndex = index
62 | }
63 | // 保存打开的页面Index
64 | self.rx.didSelect.subscribe(onNext: { _ in
65 | Settings[.selectedViewControllerIndex] = self.selectedIndex
66 | }).disposed(by: rx.disposeBag)
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Controller/BarkSFSafariViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BarkSFSafariViewController.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2018/6/26.
6 | // Copyright © 2018 Fin. All rights reserved.
7 | //
8 |
9 | import SafariServices
10 | import UIKit
11 |
12 | class BarkSFSafariViewController: SFSafariViewController {
13 | override var preferredStatusBarStyle: UIStatusBarStyle {
14 | return .default
15 | }
16 |
17 | deinit {
18 | if #available(iOS 16.0, *) {
19 | Task {
20 | await SFSafariViewController.DataStore.default.clearWebsiteData()
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Controller/BarkSplitViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BarkSplitViewController.swift
3 | // Bark
4 | //
5 | // Created by sidguan on 2024/6/30.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import Material
10 | import UIKit
11 |
12 | @available(iOS 14, *)
13 | class BarkSplitViewController: UISplitViewController {
14 | let sectionViewController = SectionViewController_iPad(viewModel: SectionViewModel())
15 | // Compact 下替换显示成 BarkTabBarController
16 | let compactController = BarkTabBarController()
17 | override func viewDidLoad() {
18 | super.viewDidLoad()
19 | self.preferredDisplayMode = .oneBesideSecondary
20 | self.preferredSplitBehavior = .tile
21 | self.delegate = self
22 | initViewControllers()
23 | }
24 |
25 | func initViewControllers() {
26 | self.setViewController(sectionViewController, for: .primary)
27 | // 设置默认打开页面
28 | let index: Int = Settings[.selectedViewControllerIndex] ?? 0
29 | self.setViewController(sectionViewController.viewControllers[index], for: .secondary)
30 | DispatchQueue.main.async {
31 | self.sectionViewController.tableView.selectRow(at: IndexPath(row: index, section: 0), animated: false, scrollPosition: .none)
32 | }
33 | self.setViewController(compactController, for: .compact)
34 | }
35 | }
36 |
37 | @available(iOS 14, *)
38 | extension BarkSplitViewController: UISplitViewControllerDelegate {
39 | // 同步 sectionViewController 和 compactController 当前显示页面
40 | func splitViewControllerDidCollapse(_ svc: UISplitViewController) {
41 | guard let index: Int = Settings[.selectedViewControllerIndex] else {
42 | return
43 | }
44 | self.compactController.selectedIndex = index
45 | }
46 |
47 | func splitViewControllerDidExpand(_ svc: UISplitViewController) {
48 | guard let index: Int = Settings[.selectedViewControllerIndex] else {
49 | return
50 | }
51 | self.sectionViewController.tableView.selectRow(at: IndexPath(row: index, section: 0), animated: false, scrollPosition: .none)
52 | self.setViewController(self.sectionViewController.viewControllers[index], for: .secondary)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Controller/BarkTabBarController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BarkTabBarController.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2024/8/20.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import Material
10 | import UIKit
11 |
12 | class BarkTabBarController: StateStorageTabBarController {
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 | self.tabBar.tintColor = BKColor.grey.darken4
16 |
17 | self.viewControllers = [
18 | BarkNavigationController(rootViewController: HomeViewController(viewModel: HomeViewModel())),
19 | BarkNavigationController(rootViewController: MessageListViewController(viewModel: MessageListViewModel())),
20 | BarkNavigationController(rootViewController: MessageSettingsViewController(viewModel: MessageSettingsViewModel()))
21 | ]
22 |
23 | let tabBarItems = [UITabBarItem(title: NSLocalizedString("service"), image: UIImage(named: "baseline_gite_black_24pt"), tag: 0),
24 | UITabBarItem(title: NSLocalizedString("historyMessage"), image: Icon.history, tag: 1),
25 | UITabBarItem(title: NSLocalizedString("settings"), image: UIImage(named: "baseline_manage_accounts_black_24pt"), tag: 2)]
26 | for (index, viewController) in self.viewControllers!.enumerated() {
27 | viewController.tabBarItem = tabBarItems[index]
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Controller/BaseViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseViewController.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2018/6/25.
6 | // Copyright © 2018 Fin. All rights reserved.
7 | //
8 |
9 | import Material
10 | import UIKit
11 |
12 | class BaseViewController: UIViewController where T: ViewModel {
13 | let viewModel: T
14 | init(viewModel: T) {
15 | self.viewModel = viewModel
16 | super.init(nibName: nil, bundle: nil)
17 | }
18 |
19 | @available(*, unavailable)
20 | required init?(coder: NSCoder) {
21 | fatalError("init(coder:) has not been implemented")
22 | }
23 |
24 | override var preferredStatusBarStyle: UIStatusBarStyle {
25 | return .lightContent
26 | }
27 |
28 | override func viewDidLoad() {
29 | super.viewDidLoad()
30 | self.view.backgroundColor = BKColor.background.primary
31 |
32 | if UIDevice.current.userInterfaceIdiom == .pad {
33 | navigationItem.largeTitleDisplayMode = .never
34 | } else {
35 | navigationItem.largeTitleDisplayMode = .automatic
36 | }
37 | makeUI()
38 | }
39 |
40 | var isViewModelBinded = false
41 | override func viewWillAppear(_ animated: Bool) {
42 | super.viewWillAppear(animated)
43 | if !isViewModelBinded {
44 | isViewModelBinded = true
45 | self.bindViewModel()
46 | }
47 | }
48 |
49 | func makeUI() {}
50 |
51 | func bindViewModel() {}
52 | }
53 |
--------------------------------------------------------------------------------
/Controller/QRScannerViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // QRScannerViewController.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2022/3/10.
6 | // Copyright © 2022 Fin. All rights reserved.
7 | //
8 |
9 | import MercariQRScanner
10 | import RxCocoa
11 | import RxSwift
12 | import UIKit
13 |
14 | class QRScannerViewController: UIViewController {
15 | var scannerDidSuccess: Observable {
16 | return self.rx.methodInvoked(#selector(didSeccess(code:))).map { a in
17 | try castOrThrow(String.self, a[0])
18 | }
19 | }
20 |
21 | let closeButton: UIButton = {
22 | let closeButton = UIButton(type: .custom)
23 | closeButton.setImage(UIImage(named: "baseline_close_white_48pt"), for: .normal)
24 | closeButton.tintColor = UIColor.white
25 | closeButton.backgroundColor = UIColor(white: 0, alpha: 0.2)
26 | closeButton.layer.cornerRadius = 40
27 | closeButton.clipsToBounds = true
28 | return closeButton
29 | }()
30 |
31 | override func viewDidLoad() {
32 | super.viewDidLoad()
33 | self.view.backgroundColor = UIColor.black
34 |
35 | let qrScannerView = QRScannerView(frame: view.bounds)
36 | qrScannerView.configure(delegate: self)
37 | view.addSubview(qrScannerView)
38 |
39 | view.addSubview(closeButton)
40 | closeButton.snp.makeConstraints { make in
41 | make.bottom.equalToSuperview().offset(-120)
42 | make.centerX.equalToSuperview()
43 | make.width.height.equalTo(80)
44 | }
45 | closeButton.rx.tap.subscribe { [weak self] in
46 | self?.dismiss(animated: true, completion: nil)
47 | } onError: { _ in }.disposed(by: rx.disposeBag)
48 |
49 | qrScannerView.startRunning()
50 | }
51 | }
52 |
53 | extension QRScannerViewController: QRScannerViewDelegate {
54 | func qrScannerView(_ qrScannerView: QRScannerView, didFailure error: QRScannerError) {
55 | self.showSnackbar(text: error.rawString())
56 | }
57 |
58 | func qrScannerView(_ qrScannerView: QRScannerView, didSuccess code: String) {
59 | self.didSeccess(code: code)
60 | self.dismiss(animated: true, completion: nil)
61 | }
62 |
63 | @objc private func didSeccess(code: String) {}
64 | }
65 |
--------------------------------------------------------------------------------
/Controller/SectionViewModel-iPad.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SectionViewModel-iPad.swift
3 | // Bark
4 | //
5 | // Created by sidguan on 2024/7/1.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import RxCocoa
11 | import RxDataSources
12 | import RxSwift
13 | import Material
14 |
15 | struct SectionItem {
16 | let image: UIImage?
17 | let title: String
18 | }
19 |
20 | class SectionViewModel: ViewModel, ViewModelType {
21 | struct Input {
22 | // var sectionSelected: Driver
23 | }
24 |
25 | struct Output {
26 | var items: Observable<[SectionModel]>
27 | // var selectedItem: Observable
28 | }
29 |
30 | func initSectionItems() -> Observable<[SectionModel]> {
31 | let sectionItems = [
32 | SectionItem(image: UIImage(named: "baseline_gite_black_24pt"), title: NSLocalizedString("service")),
33 | SectionItem(image: Icon.history, title: NSLocalizedString("historyMessage")),
34 | SectionItem(image: UIImage(named: "baseline_manage_accounts_black_24pt"), title: NSLocalizedString("settings")),
35 | ]
36 | let section = [SectionModel(model: "", items: sectionItems)]
37 | return Observable.just(section)
38 | }
39 |
40 | func transform(input: Input) -> Output {
41 | let sectionItems = initSectionItems()
42 | return Output(
43 | items: sectionItems
44 | )
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | gem "cocoapods"
4 | gem "fastlane"
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Feng
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Model/Message.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Message.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/5/25.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import RealmSwift
10 | import UIKit
11 |
12 | class Message: Object {
13 | @objc dynamic var id = NSUUID().uuidString
14 | @objc dynamic var title: String?
15 | @objc dynamic var subtitle: String?
16 | @objc dynamic var body: String?
17 | @objc dynamic var url: String?
18 | @objc dynamic var image: String?
19 | @objc dynamic var group: String?
20 | @objc dynamic var createDate: Date?
21 |
22 | override class func primaryKey() -> String? {
23 | return "id"
24 | }
25 |
26 | override class func indexedProperties() -> [String] {
27 | return ["group", "createDate"]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Model/MessageDeleteTimeRange.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MessageDeleteTimeRange.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 1/7/25.
6 | // Copyright © 2025 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum MessageDeleteTimeRange {
12 | /// 最近一小时
13 | case lastHour
14 | /// 今天
15 | case today
16 | /// 今天和昨天
17 | case todayAndYesterday
18 | /// 最近一个月
19 | case lastMonth
20 | /// 全部时间
21 | case allTime
22 |
23 | /// 一小时之前
24 | case beforeOneHour
25 | /// 一天之前
26 | case beforeToday
27 | /// 昨天之前
28 | case beforeYesterday
29 | /// 一月之前
30 | case beforeOneMonth
31 |
32 | var string: String {
33 | switch self {
34 | case .lastHour:
35 | return NSLocalizedString("lastHour")
36 | case .today:
37 | return NSLocalizedString("today")
38 | case .todayAndYesterday:
39 | return NSLocalizedString("todayAndYesterday")
40 | case .lastMonth:
41 | return NSLocalizedString("lastMonth")
42 | case .allTime:
43 | return NSLocalizedString("allTime")
44 | case .beforeOneHour:
45 | return NSLocalizedString("beforeAnHour")
46 | case .beforeToday:
47 | return NSLocalizedString("beforeToday")
48 | case .beforeYesterday:
49 | return NSLocalizedString("beforeYesterday")
50 | case .beforeOneMonth:
51 | return NSLocalizedString("beforeAMonth")
52 | }
53 | }
54 |
55 | var startDate: Date {
56 | switch self {
57 | case .lastHour:
58 | return Date.lastHour
59 | case .today:
60 | return Date().startOfDay
61 | case .todayAndYesterday:
62 | return Date.yesterday
63 | case .lastMonth:
64 | return Date.lastMonth
65 | case .allTime,
66 | .beforeOneHour,
67 | .beforeToday,
68 | .beforeYesterday,
69 | .beforeOneMonth:
70 | return Date(timeIntervalSince1970: 0)
71 | }
72 | }
73 |
74 | var endDate: Date {
75 | switch self {
76 | case .lastHour,
77 | .today,
78 | .todayAndYesterday,
79 | .lastMonth,
80 | .allTime:
81 | return Date()
82 | case .beforeOneHour:
83 | return Date.lastHour
84 | case .beforeToday:
85 | return Date().startOfDay
86 | case .beforeYesterday:
87 | return Date.yesterday
88 | case .beforeOneMonth:
89 | return Date.lastMonth
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Model/MessageSection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MessageTableViewCellViewModel.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/11/21.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import Differentiator
10 | import Foundation
11 | import RxCocoa
12 | import RxDataSources
13 |
14 | enum MessageListCellItem: Equatable {
15 | /// 单条消息
16 | case message(model: MessageItemModel)
17 | /// 一组消息,可以收缩折叠
18 | case messageGroup(name: String, totalCount: Int, messages: [MessageItemModel])
19 |
20 | // 确定 cell 内部是否需要更新
21 | static func == (lhs: Self, rhs: Self) -> Bool {
22 | switch (lhs, rhs) {
23 | case (.message(let l), .message(let r)):
24 | return l.id == r.id && l.dateText == r.dateText
25 | case (.messageGroup(let l, _, let lMessages), .messageGroup(let r, _, let rMessages)):
26 | if l != r {
27 | return false
28 | }
29 | if lMessages.first?.dateText != rMessages.first?.dateText {
30 | return false
31 | }
32 | if lMessages.count != rMessages.count {
33 | return false
34 | }
35 | for (lMessage, rMessage) in zip(lMessages, rMessages) {
36 | if lMessage.id != rMessage.id {
37 | return false
38 | }
39 | }
40 | return true
41 | default:
42 | return false
43 | }
44 | }
45 | }
46 |
47 | extension MessageListCellItem: IdentifiableType {
48 | typealias Identity = String
49 |
50 | // 确定整个 cell 是否删除或替换
51 | var identity: String {
52 | switch self {
53 | case .message(let model):
54 | return "list_\(model.id)"
55 | case .messageGroup(_, _, let messages):
56 | return "group_\(messages.first?.group ?? NSLocalizedString("Default"))"
57 | }
58 | }
59 | }
60 |
61 | struct MessageSection {
62 | var header: String
63 | var messages: [MessageListCellItem]
64 | }
65 |
66 | extension MessageSection: AnimatableSectionModelType {
67 | typealias Item = MessageListCellItem
68 | typealias Identity = String
69 |
70 | var items: [MessageListCellItem] {
71 | return self.messages
72 | }
73 |
74 | init(original: MessageSection, items: [MessageListCellItem]) {
75 | self = original
76 | self.messages = items
77 | }
78 |
79 | var identity: String {
80 | return header
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/Model/Object+Dictionary.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Object+Dictionary.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2022/10/20.
6 | // Copyright © 2022 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import RealmSwift
11 |
12 | extension Object {
13 | func toDictionary() -> [String: AnyObject] {
14 | var dicProps = [String: AnyObject]()
15 | self.objectSchema.properties.forEach { property in
16 | if property.isArray {
17 | var arr: [[String: AnyObject]] = []
18 | for obj in self.dynamicList(property.name) {
19 | arr.append(obj.toDictionary())
20 | }
21 | dicProps[property.name] = arr as AnyObject
22 | } else if let value = self[property.name] as? Object {
23 | dicProps[property.name] = value.toDictionary() as AnyObject
24 | } else if let value = self[property.name] as? Date {
25 | dicProps[property.name] = Int64(value.timeIntervalSince1970) as AnyObject
26 | } else {
27 | let value = self[property.name]
28 | dicProps[property.name] = value as AnyObject
29 | }
30 | }
31 | return dicProps
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Model/PreviewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PreviewModel.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/11/23.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | class PreviewModel: NSObject {
13 | var title: String?
14 | var body: String?
15 | var notice: String?
16 | var queryParameter: String?
17 | var image: UIImage?
18 | var moreInfo: String?
19 | var moreViewModel: ViewModel?
20 |
21 | init(title: String? = nil,
22 | body: String? = nil,
23 | notice: String? = nil,
24 | queryParameter: String? = nil,
25 | image: UIImage? = nil,
26 | moreInfo: String? = nil,
27 | moreViewModel: ViewModel? = nil)
28 | {
29 | self.title = title
30 | self.body = body
31 | self.notice = notice
32 | self.queryParameter = queryParameter
33 | self.image = image
34 | self.moreInfo = moreInfo
35 | self.moreViewModel = moreViewModel
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/NotificationServiceExtension/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | NotificationServiceExtension
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSExtension
24 |
25 | NSExtensionAttributes
26 |
27 | IntentsSupported
28 |
29 | INSendMessageIntent
30 |
31 |
32 | NSExtensionPointIdentifier
33 | com.apple.usernotifications.service
34 | NSExtensionPrincipalClass
35 | $(PRODUCT_MODULE_NAME).NotificationService
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/NotificationServiceExtension/NotificationService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationService.swift
3 | // NotificationServiceExtension
4 | //
5 | // Created by huangfeng on 2018/12/17.
6 | // Copyright © 2018 Fin. All rights reserved.
7 | //
8 |
9 | import UserNotifications
10 |
11 | class NotificationService: UNNotificationServiceExtension {
12 | /// 当前正在运行的 Processor
13 | var currentNotificationProcessor: NotificationContentProcessor? = nil
14 | /// 当前 ContentHandler,主要用来 serviceExtensionTimeWillExpire 时,传递给 Processor 用来交付推送。
15 | var currentContentHandler: ((UNNotificationContent) -> Void)? = nil
16 |
17 | override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
18 | Task {
19 | guard var bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) else {
20 | contentHandler(request.content)
21 | return
22 | }
23 | self.currentContentHandler = contentHandler
24 |
25 | // 所有的 processor, 按顺序从上往下对推送进行处理
26 | // ciphertext 需要放在最前面,有可能所有的推送数据都在密文里
27 | let processors: [NotificationContentProcessorItem] = [
28 | .ciphertext,
29 | .level,
30 | .badge,
31 | .autoCopy,
32 | .archive,
33 | .setIcon,
34 | .setImage,
35 | .mute,
36 | .call
37 | ]
38 |
39 | // 各个 processor 依次对推送进行处理
40 | for processor in processors.map({ $0.processor }) {
41 | do {
42 | self.currentNotificationProcessor = processor
43 | bestAttemptContent = try await processor.process(identifier: request.identifier, content: bestAttemptContent)
44 | } catch NotificationContentProcessorError.error(let content) {
45 | contentHandler(content)
46 | return
47 | }
48 | }
49 |
50 | // 处理完后交付推送
51 | contentHandler(bestAttemptContent)
52 | }
53 | }
54 |
55 | override func serviceExtensionTimeWillExpire() {
56 | super.serviceExtensionTimeWillExpire()
57 | if let handler = self.currentContentHandler {
58 | self.currentNotificationProcessor?.serviceExtensionTimeWillExpire(contentHandler: handler)
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/NotificationServiceExtension/NotificationServiceExtension.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.application-groups
6 |
7 | group.bark
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/NotificationServiceExtension/Processor/ArchiveProcessor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ArchiveProcessor.swift
3 | // NotificationServiceExtension
4 | //
5 | // Created by huangfeng on 2024/5/29.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import RealmSwift
11 |
12 | class ArchiveProcessor: NotificationContentProcessor {
13 | private lazy var realm: Realm? = {
14 | Realm.Configuration.defaultConfiguration = kRealmDefaultConfiguration
15 | return try? Realm()
16 | }()
17 |
18 | func process(identifier: String, content bestAttemptContent: UNMutableNotificationContent) async throws -> UNMutableNotificationContent {
19 | let userInfo = bestAttemptContent.userInfo
20 |
21 | var isArchive: Bool = ArchiveSettingManager.shared.isArchive
22 | if let archive = userInfo["isarchive"] as? String {
23 | isArchive = archive == "1" ? true : false
24 | }
25 |
26 | if isArchive {
27 | let alert = (userInfo["aps"] as? [String: Any])?["alert"] as? [String: Any]
28 | let title = alert?["title"] as? String
29 | let subtitle = alert?["subtitle"] as? String
30 | let body = alert?["body"] as? String
31 | let url = userInfo["url"] as? String
32 | let group = userInfo["group"] as? String
33 | let image = userInfo["image"] as? String
34 |
35 | try? realm?.write {
36 | let message = Message()
37 | message.title = title
38 | message.subtitle = subtitle
39 | message.body = body
40 | message.url = url
41 | message.image = image
42 | message.group = group
43 | message.createDate = Date()
44 | realm?.add(message)
45 | }
46 | }
47 | return bestAttemptContent
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/NotificationServiceExtension/Processor/AutoCopyProcessor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutoCopyProcessor.swift
3 | // NotificationServiceExtension
4 | //
5 | // Created by huangfeng on 2024/5/29.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class AutoCopyProcessor: NotificationContentProcessor {
12 | func process(identifier: String, content bestAttemptContent: UNMutableNotificationContent) async throws -> UNMutableNotificationContent {
13 | let userInfo = bestAttemptContent.userInfo
14 | if userInfo["autocopy"] as? String == "1"
15 | || userInfo["automaticallycopy"] as? String == "1"
16 | {
17 | if let copy = userInfo["copy"] as? String {
18 | UIPasteboard.general.string = copy
19 | } else {
20 | UIPasteboard.general.string = bestAttemptContent.body
21 | }
22 | }
23 | return bestAttemptContent
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/NotificationServiceExtension/Processor/BadgeProcessor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BadgeProcessor.swift
3 | // NotificationServiceExtension
4 | //
5 | // Created by huangfeng on 2024/5/29.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// 通知角标
12 | class BadgeProcessor: NotificationContentProcessor {
13 | func process(identifier: String, content bestAttemptContent: UNMutableNotificationContent) async throws -> UNMutableNotificationContent {
14 | if let badgeStr = bestAttemptContent.userInfo["badge"] as? String, let badge = Int(badgeStr) {
15 | bestAttemptContent.badge = NSNumber(value: badge)
16 | }
17 | return bestAttemptContent
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/NotificationServiceExtension/Processor/ImageDownloader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImageDownloader.swift
3 | // NotificationServiceExtension
4 | //
5 | // Created by huangfeng on 2024/5/29.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Kingfisher
11 |
12 | class ImageDownloader {
13 | /// 保存图片到缓存中
14 | /// - Parameters:
15 | /// - cache: 使用的缓存
16 | /// - data: 图片 Data 数据
17 | /// - key: 缓存 Key
18 | class func storeImage(cache: ImageCache, data: Data, key: String) async {
19 | return await withCheckedContinuation { continuation in
20 | cache.storeToDisk(data, forKey: key, expiration: StorageExpiration.never) { _ in
21 | continuation.resume()
22 | }
23 | }
24 | }
25 |
26 | /// 使用 Kingfisher.ImageDownloader 下载图片
27 | /// - Parameter url: 下载的图片URL
28 | /// - Returns: 返回 Result
29 | class func downloadImage(url: URL) async -> Result {
30 | return await withCheckedContinuation { continuation in
31 | Kingfisher.ImageDownloader.default.downloadImage(with: url, options: nil) { result in
32 | continuation.resume(returning: result)
33 | }
34 | }
35 | }
36 |
37 | /// 下载推送图片
38 | /// - Parameter imageUrl: 图片URL字符串
39 | /// - Returns: 保存在本地中的`图片 File URL`
40 | class func downloadImage(_ imageUrl: String) async -> String? {
41 | guard let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark"),
42 | let cache = try? ImageCache(name: "shared", cacheDirectoryURL: groupUrl),
43 | let imageResource = URL(string: imageUrl)
44 | else {
45 | return nil
46 | }
47 |
48 | // 先查看图片缓存
49 | if cache.diskStorage.isCached(forKey: imageResource.cacheKey) {
50 | return cache.cachePath(forKey: imageResource.cacheKey)
51 | }
52 |
53 | // 下载图片
54 | guard let result = try? await downloadImage(url: imageResource).get() else {
55 | return nil
56 | }
57 | // 缓存图片
58 | await storeImage(cache: cache, data: result.originalData, key: imageResource.cacheKey)
59 |
60 | return cache.cachePath(forKey: imageResource.cacheKey)
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/NotificationServiceExtension/Processor/ImageProcessor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImageProcessor.swift
3 | // NotificationServiceExtension
4 | //
5 | // Created by huangfeng on 2024/5/29.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import MobileCoreServices
11 |
12 | class ImageProcessor: NotificationContentProcessor {
13 | func process(identifier: String, content bestAttemptContent: UNMutableNotificationContent) async throws -> UNMutableNotificationContent {
14 | let userInfo = bestAttemptContent.userInfo
15 | guard let imageUrl = userInfo["image"] as? String,
16 | let imageFileUrl = await ImageDownloader.downloadImage(imageUrl)
17 | else {
18 | return bestAttemptContent
19 | }
20 |
21 | let copyDestUrl = URL(fileURLWithPath: imageFileUrl).appendingPathExtension(".tmp")
22 | // 将图片缓存复制一份,推送使用完后会自动删除,但图片缓存需要留着以后在历史记录里查看
23 | try? FileManager.default.copyItem(
24 | at: URL(fileURLWithPath: imageFileUrl),
25 | to: copyDestUrl
26 | )
27 |
28 | if let attachment = try? UNNotificationAttachment(
29 | identifier: "image",
30 | url: copyDestUrl,
31 | options: [UNNotificationAttachmentOptionsTypeHintKey: kUTTypePNG]
32 | ) {
33 | bestAttemptContent.attachments = [attachment]
34 | }
35 | return bestAttemptContent
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/NotificationServiceExtension/Processor/MuteProcessor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MuteProcessor.swift
3 | // NotificationServiceExtension
4 | //
5 | // Created by huangfeng on 11/6/24.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MuteProcessor: NotificationContentProcessor {
12 | func process(identifier: String, content bestAttemptContent: UNMutableNotificationContent) async throws -> UNMutableNotificationContent {
13 | let groupName = bestAttemptContent.threadIdentifier
14 | guard let date = GroupMuteSettingManager().settings[groupName], date > Date() else {
15 | return bestAttemptContent
16 | }
17 | // 需要静音
18 | if #available(iOSApplicationExtension 15.0, *) {
19 | bestAttemptContent.interruptionLevel = .passive
20 | }
21 | return bestAttemptContent
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/NotificationServiceExtension/Processor/NotificationContentProcessor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationContentProcessor.swift
3 | // NotificationServiceExtension
4 | //
5 | // Created by huangfeng on 2024/5/29.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | @_exported import UserNotifications
11 |
12 | enum NotificationContentProcessorItem {
13 | case ciphertext
14 | case level
15 | case badge
16 | case autoCopy
17 | case archive
18 | case setIcon
19 | case setImage
20 | case call
21 | case mute
22 |
23 | var processor: NotificationContentProcessor {
24 | switch self {
25 | case .ciphertext:
26 | return CiphertextProcessor()
27 | case .level:
28 | return LevelProcessor()
29 | case .badge:
30 | return BadgeProcessor()
31 | case .autoCopy:
32 | return AutoCopyProcessor()
33 | case .archive:
34 | return ArchiveProcessor()
35 | case .setIcon:
36 | return IconProcessor()
37 | case .setImage:
38 | return ImageProcessor()
39 | case .call:
40 | return CallProcessor()
41 | case .mute:
42 | return MuteProcessor()
43 | }
44 | }
45 | }
46 |
47 | enum NotificationContentProcessorError: Swift.Error {
48 | case error(content: UNMutableNotificationContent)
49 | }
50 |
51 | public protocol NotificationContentProcessor {
52 | /// 处理 UNMutableNotificationContent
53 | /// - Parameters:
54 | /// - identifier: request.identifier, 有些 Processor 需要,例如 CallProcessor 需要这个去添加 LocalNotification
55 | /// - bestAttemptContent: 需要处理的 UNMutableNotificationContent
56 | /// - Returns: 处理成功后的 UNMutableNotificationContent
57 | /// - Throws: 处理失败后,应该中断处理
58 | func process(identifier: String, content bestAttemptContent: UNMutableNotificationContent) async throws -> UNMutableNotificationContent
59 |
60 | /// serviceExtension 即将终止,不管 processor 是否处理完成,最好立即调用 contentHandler 交付已完成的部分,否则会原样展示服务器传递过来的推送
61 | func serviceExtensionTimeWillExpire(contentHandler: (UNNotificationContent) -> Void)
62 | }
63 |
64 | extension NotificationContentProcessor {
65 | func serviceExtensionTimeWillExpire(contentHandler: (UNNotificationContent) -> Void) {}
66 | }
67 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 |
3 | platform:ios,'13.0'
4 | inhibit_all_warnings!
5 | use_modular_headers!
6 |
7 |
8 | def pods
9 | pod 'SnapKit'
10 | pod 'Material'
11 | pod 'SVProgressHUD'
12 | pod 'FDFullscreenPopGesture'
13 | pod 'Moya/RxSwift'
14 | pod 'ObjectMapper'
15 | pod 'SwiftyJSON'
16 | pod 'DefaultsKit'
17 | pod 'RealmSwift'
18 | pod 'CryptoSwift'
19 | pod 'IQKeyboardManagerSwift/IQKeyboardToolbarManager'
20 |
21 | pod 'RxSwift'
22 | pod 'RxCocoa'
23 | pod 'RxGesture'
24 | pod 'RxDataSources'
25 | pod 'NSObject+Rx'
26 |
27 | pod 'MJRefresh'
28 | pod 'Kingfisher'
29 | pod 'MercariQRScanner', :git => 'https://github.com/Finb/QRScanner'
30 | pod 'DropDown'
31 | pod 'ImageViewer.swift'
32 |
33 | pod 'SwiftyStoreKit'
34 | end
35 |
36 | target 'Bark' do
37 | pods
38 |
39 | target 'BarkTests' do
40 | inherit! :search_paths
41 | end
42 |
43 | end
44 |
45 |
46 | target 'NotificationServiceExtension' do
47 | pod 'RealmSwift'
48 | pod 'Kingfisher'
49 | pod 'CryptoSwift'
50 | pod 'SwiftyJSON'
51 | end
52 |
53 | target 'NotificationContentExtension' do
54 | pod 'Kingfisher'
55 | end
56 |
57 |
58 | post_install do |installer|
59 | installer.pods_project.targets.each do |target|
60 | target.build_configurations.each do |config|
61 | if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 13.0
62 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
63 | end
64 | config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
65 | end
66 | end
67 | end
68 |
--------------------------------------------------------------------------------
/Sounds/alarm.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/alarm.caf
--------------------------------------------------------------------------------
/Sounds/anticipate.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/anticipate.caf
--------------------------------------------------------------------------------
/Sounds/bell.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/bell.caf
--------------------------------------------------------------------------------
/Sounds/birdsong.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/birdsong.caf
--------------------------------------------------------------------------------
/Sounds/bloom.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/bloom.caf
--------------------------------------------------------------------------------
/Sounds/calypso.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/calypso.caf
--------------------------------------------------------------------------------
/Sounds/chime.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/chime.caf
--------------------------------------------------------------------------------
/Sounds/choo.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/choo.caf
--------------------------------------------------------------------------------
/Sounds/descent.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/descent.caf
--------------------------------------------------------------------------------
/Sounds/electronic.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/electronic.caf
--------------------------------------------------------------------------------
/Sounds/fanfare.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/fanfare.caf
--------------------------------------------------------------------------------
/Sounds/glass.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/glass.caf
--------------------------------------------------------------------------------
/Sounds/gotosleep.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/gotosleep.caf
--------------------------------------------------------------------------------
/Sounds/healthnotification.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/healthnotification.caf
--------------------------------------------------------------------------------
/Sounds/horn.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/horn.caf
--------------------------------------------------------------------------------
/Sounds/ladder.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/ladder.caf
--------------------------------------------------------------------------------
/Sounds/mailsent.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/mailsent.caf
--------------------------------------------------------------------------------
/Sounds/minuet.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/minuet.caf
--------------------------------------------------------------------------------
/Sounds/multiwayinvitation.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/multiwayinvitation.caf
--------------------------------------------------------------------------------
/Sounds/newmail.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/newmail.caf
--------------------------------------------------------------------------------
/Sounds/newsflash.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/newsflash.caf
--------------------------------------------------------------------------------
/Sounds/noir.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/noir.caf
--------------------------------------------------------------------------------
/Sounds/paymentsuccess.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/paymentsuccess.caf
--------------------------------------------------------------------------------
/Sounds/shake.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/shake.caf
--------------------------------------------------------------------------------
/Sounds/sherwoodforest.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/sherwoodforest.caf
--------------------------------------------------------------------------------
/Sounds/silence.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/silence.caf
--------------------------------------------------------------------------------
/Sounds/spell.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/spell.caf
--------------------------------------------------------------------------------
/Sounds/suspense.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/suspense.caf
--------------------------------------------------------------------------------
/Sounds/telegraph.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/telegraph.caf
--------------------------------------------------------------------------------
/Sounds/tiptoes.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/tiptoes.caf
--------------------------------------------------------------------------------
/Sounds/typewriters.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/typewriters.caf
--------------------------------------------------------------------------------
/Sounds/update.caf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/Sounds/update.caf
--------------------------------------------------------------------------------
/View/AddSoundCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AddSoundCell.swift
3 | // Bark
4 | //
5 | // Created by Fin on 2024/3/29.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class AddSoundCell: UITableViewCell {
12 | let button: UIButton = {
13 | let button = UIButton(type: .system)
14 | button.setTitle(NSLocalizedString("uploadSound"), for: .normal)
15 | button.setImage(UIImage(named: "music_note-music_note_symbol"), for: .normal)
16 | button.setTitleColor(BKColor.lightBlue.darken3, for: .normal)
17 | button.tintColor = BKColor.lightBlue.darken3
18 | button.titleLabel?.font = UIFont.preferredFont(ofSize: 16)
19 | button.titleLabel?.adjustsFontForContentSizeCategory = true
20 | // 从 UITableView didSelectRowAt 那响应点击事件
21 | button.isUserInteractionEnabled = false
22 | return button
23 | }()
24 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
25 | super.init(style: style, reuseIdentifier: reuseIdentifier)
26 | self.selectionStyle = .none
27 | contentView.addSubview(button)
28 | button.snp.makeConstraints { make in
29 | make.edges.equalToSuperview()
30 | make.height.equalTo(44)
31 | }
32 | }
33 |
34 | required init?(coder: NSCoder) {
35 | fatalError("init(coder:) has not been implemented")
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/View/ArchiveSettingCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ArchiveSettingCell.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/5/29.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ArchiveSettingCell: BaseTableViewCell {
12 | let switchButton: UISwitch = {
13 | let btn = UISwitch()
14 | return btn
15 | }()
16 |
17 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
18 | super.init(style: style, reuseIdentifier: reuseIdentifier)
19 | self.selectionStyle = .none
20 | self.backgroundColor = BKColor.background.secondary
21 | self.textLabel?.text = NSLocalizedString("defaultArchiveSettings")
22 |
23 | contentView.addSubview(switchButton)
24 | switchButton.snp.makeConstraints { make in
25 | make.right.equalToSuperview().offset(-16)
26 | make.centerY.equalToSuperview()
27 | }
28 | }
29 |
30 | @available(*, unavailable)
31 | required init?(coder aDecoder: NSCoder) {
32 | fatalError("init(coder:) has not been implemented")
33 | }
34 |
35 | override func bindViewModel(model: ArchiveSettingCellViewModel) {
36 | super.bindViewModel(model: model)
37 | (self.switchButton.rx.isOn <-> model.on)
38 | .disposed(by: rx.reuseBag)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/View/ArchiveSettingCellViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ArchiveSettingCellViewModel.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/11/20.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import RxCocoa
11 | class ArchiveSettingCellViewModel: ViewModel {
12 | var on: BehaviorRelay
13 | init(on: BehaviorRelay) {
14 | self.on = on
15 | super.init()
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/View/BKButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BKButton.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/9/23.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol AlignmentRectInsetsOverridable: AnyObject {
12 | var alignmentRectInsetsOverride: UIEdgeInsets? { get set }
13 | }
14 |
15 | protocol HitTestSlopable: AnyObject {
16 | var hitTestSlop: UIEdgeInsets { get set }
17 | }
18 |
19 | class BKButton: UIButton, HitTestSlopable, AlignmentRectInsetsOverridable {
20 | var hitTestSlop = UIEdgeInsets.zero
21 | override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
22 | if hitTestSlop == UIEdgeInsets.zero {
23 | return super.point(inside: point, with: event)
24 | }
25 | else {
26 | return self.bounds.inset(by: hitTestSlop).contains(point)
27 | }
28 | }
29 |
30 | var alignmentRectInsetsOverride: UIEdgeInsets?
31 | override var alignmentRectInsets: UIEdgeInsets {
32 | return alignmentRectInsetsOverride ?? super.alignmentRectInsets
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/View/BKDropDownCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BKDropDownCellTableViewCell.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2023/2/9.
6 | // Copyright © 2023 Fin. All rights reserved.
7 | //
8 |
9 | import DropDown
10 | import UIKit
11 |
12 | class BKDropDownCell: DropDownCell {
13 |
14 | @IBOutlet var selectBackgroundView: UIView!
15 |
16 | override func awakeFromNib() {
17 | super.awakeFromNib()
18 | self.backgroundColor = BKColor.white
19 | self.selectBackgroundView.layer.cornerRadius = 10
20 | self.selectBackgroundView.clipsToBounds = true
21 | }
22 |
23 | override func setSelected(_ selected: Bool, animated: Bool) {
24 |
25 | let executeSelection: () -> Void = { [weak self] in
26 | guard let `self` = self else { return }
27 |
28 | let selectedBackgroundColor = BKColor.grey.lighten5
29 | if selected {
30 | self.selectBackgroundView.backgroundColor = selectedBackgroundColor
31 | self.optionLabel.textColor = BKColor.grey.darken4
32 | } else {
33 | self.selectBackgroundView.backgroundColor = .clear
34 | self.optionLabel.textColor = BKColor.grey.darken3
35 | }
36 | }
37 |
38 | if animated {
39 | UIView.animate(withDuration: 0.3, animations: {
40 | executeSelection()
41 | })
42 | } else {
43 | executeSelection()
44 | }
45 |
46 | accessibilityTraits = selected ? .selected : .none
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/View/BKLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BKLabel.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/5/29.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class BKLabel: UILabel {
12 | var hitTestSlop = UIEdgeInsets.zero
13 |
14 | override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
15 | if hitTestSlop == UIEdgeInsets.zero {
16 | return super.point(inside: point, with: event)
17 | }
18 | else {
19 | return self.bounds.inset(by: hitTestSlop).contains(point)
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/View/BaseTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseTableViewCell.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/11/20.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class BaseTableViewCell: UITableViewCell where T: ViewModel {
12 | var viewModel: T?
13 | func bindViewModel(model: T) {
14 | self.viewModel = model
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/View/DonateCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DonateCell.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 11/13/24.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import SwiftyStoreKit
10 | import UIKit
11 |
12 | class DonateCell: UITableViewCell {
13 | var title: String? = nil {
14 | didSet {
15 | self.textLabel?.text = title
16 | }
17 | }
18 |
19 | var productId: String? = nil {
20 | didSet {
21 | guard let productId else { return }
22 | if let cachePriceStr = Settings["bark.price.\(productId)"] {
23 | self.detailTextLabel?.text = cachePriceStr
24 | return
25 | }
26 | // 查询价格
27 | SwiftyStoreKit.retrieveProductsInfo([productId]) { result in
28 | if let product = result.retrievedProducts.first, let price = product.localizedPrice {
29 | let priceStr = price + (product.localizedSubscriptionPeriod.isEmpty ? "" : " / \(product.localizedSubscriptionPeriod)")
30 | Settings["bark.price.\(productId)"] = priceStr
31 | self.detailTextLabel?.text = priceStr
32 | }
33 | }
34 | }
35 | }
36 |
37 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
38 | super.init(style: .value1, reuseIdentifier: reuseIdentifier)
39 | self.selectionStyle = .none
40 | self.accessoryType = .disclosureIndicator
41 | self.backgroundColor = BKColor.background.secondary
42 | self.detailTextLabel?.textColor = BKColor.grey.darken2
43 | }
44 |
45 | @available(*, unavailable)
46 | required init?(coder aDecoder: NSCoder) {
47 | fatalError("init(coder:) has not been implemented")
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/View/GesturePassTextView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GesturePassTextView.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2023/7/26.
6 | // Copyright © 2023 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class GesturePassTextView: UITextView {
12 | var superCell: UITableViewCell? = nil
13 | override func touchesBegan(_ touches: Set, with event: UIEvent?) {
14 | if let cell = superCell {
15 | cell.touchesBegan(touches, with: event)
16 | return
17 | }
18 | super.touchesBegan(touches, with: event)
19 | }
20 | override func touchesMoved(_ touches: Set, with event: UIEvent?) {
21 | if let cell = superCell {
22 | cell.touchesMoved(touches, with: event)
23 | return
24 | }
25 | super.touchesMoved(touches, with: event)
26 | }
27 | override func touchesEnded(_ touches: Set, with event: UIEvent?) {
28 | if let cell = superCell {
29 | cell.touchesEnded(touches, with: event)
30 | return
31 | }
32 | super.touchesEnded(touches, with: event)
33 | }
34 | override func touchesCancelled(_ touches: Set, with event: UIEvent?) {
35 | if let cell = superCell {
36 | cell.touchesCancelled(touches, with: event)
37 | return
38 | }
39 | super.touchesCancelled(touches, with: event)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/View/GradientButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Gradient.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2023/2/10.
6 | // Copyright © 2023 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | typealias GradientPoints = (startPoint: CGPoint, endPoint: CGPoint)
12 |
13 | enum GradientOrientation {
14 | case topRightBottomLeft
15 | case topLeftBottomRight
16 | case horizontal
17 | case vertical
18 |
19 | var startPoint: CGPoint {
20 | return points.startPoint
21 | }
22 |
23 | var endPoint: CGPoint {
24 | return points.endPoint
25 | }
26 |
27 | var points: GradientPoints {
28 | switch self {
29 | case .topRightBottomLeft:
30 | return (CGPoint(x: 0.0, y: 1.0), CGPoint(x: 1.0, y: 0.0))
31 | case .topLeftBottomRight:
32 | return (CGPoint(x: 0.0, y: 0.0), CGPoint(x: 1, y: 1))
33 | case .horizontal:
34 | return (CGPoint(x: 0.0, y: 0.5), CGPoint(x: 1.0, y: 0.5))
35 | case .vertical:
36 | return (CGPoint(x: 0.0, y: 0.0), CGPoint(x: 0.0, y: 1.0))
37 | }
38 | }
39 | }
40 |
41 | class GradientButton: UIButton {
42 | lazy var gradient: CAGradientLayer = {
43 | let gradient = CAGradientLayer()
44 | return gradient
45 | }()
46 |
47 | func applyGradient(withColours colours: [UIColor], gradientOrientation orientation: GradientOrientation) {
48 | gradient.frame = self.bounds
49 | gradient.colors = colours.map { $0.cgColor }
50 | gradient.startPoint = orientation.startPoint
51 | gradient.endPoint = orientation.endPoint
52 |
53 | if gradient.superlayer == nil {
54 | self.layer.insertSublayer(gradient, at: 0)
55 | }
56 | }
57 |
58 | override func layoutSubviews() {
59 | super.layoutSubviews()
60 | gradient.frame = self.bounds
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/View/HUD.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HUD.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2023/3/6.
6 | // Copyright © 2023 Fin. All rights reserved.
7 | //
8 |
9 | import SVProgressHUD
10 | import UIKit
11 | class BarkProgressHUD: SVProgressHUD {
12 | override class func displayDuration(for string: String?) -> TimeInterval {
13 | return min(Double((string ?? "").utf8.count) * 0.06 + 0.5, 5.0)
14 | }
15 | }
16 |
17 | open class ProgressHUD: NSObject {
18 | open class func show() {
19 | BarkProgressHUD.show()
20 | }
21 |
22 | open class func showWithClearMask() {
23 | BarkProgressHUD.show()
24 | }
25 |
26 | open class func dismiss() {
27 | BarkProgressHUD.dismiss()
28 | }
29 |
30 | open class func showWithStatus(_ status: String!) {
31 | BarkProgressHUD.show(withStatus: status)
32 | }
33 |
34 | open class func success(_ status: String!) {
35 | BarkProgressHUD.showSuccess(withStatus: status)
36 | }
37 |
38 | open class func error(_ status: String!) {
39 | BarkProgressHUD.showError(withStatus: status)
40 | }
41 |
42 | open class func inform(_ status: String!) {
43 | BarkProgressHUD.showInfo(withStatus: status)
44 | }
45 | }
46 |
47 | public func HUDSuccess(_ status: String?) {
48 | ProgressHUD.success(status ?? "")
49 | }
50 |
51 | public func HUDError(_ status: String?) {
52 | ProgressHUD.error(status ?? "")
53 | }
54 |
55 | public func HUDInform(_ status: String?) {
56 | ProgressHUD.inform(status ?? "")
57 | }
58 |
59 | public func HUDShow() {
60 | ProgressHUD.show()
61 | }
62 |
63 | public func HUDShowWithStatus(_ status: String!) {
64 | ProgressHUD.showWithStatus(status)
65 | }
66 |
67 | public func HUDDismiss() {
68 | ProgressHUD.dismiss()
69 | }
70 |
--------------------------------------------------------------------------------
/View/LabelCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LabelCell.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/5/29.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import Material
10 | import UIKit
11 |
12 | class LabelCell: UITableViewCell {
13 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
14 | super.init(style: style, reuseIdentifier: reuseIdentifier)
15 | self.selectionStyle = .none
16 |
17 | self.backgroundColor = BKColor.background.primary
18 | self.textLabel?.textColor = BKColor.grey.darken1
19 | self.textLabel?.fontSize = 12
20 | self.textLabel?.numberOfLines = 0
21 | }
22 |
23 | @available(*, unavailable)
24 | required init?(coder aDecoder: NSCoder) {
25 | fatalError("init(coder:) has not been implemented")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/View/MessageList/MessageGroupHeaderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MessageGroupHeaderView.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 12/23/24.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MessageGroupHeaderView: UIView {
12 | private let groupNameLabel: UILabel = {
13 | let label = UILabel()
14 | label.font = UIFont.preferredFont(ofSize: 16, weight: .semibold)
15 | label.textColor = BKColor.grey.darken4
16 | return label
17 | }()
18 |
19 | private let showLessAndClearView: ShowLessAndClearView = {
20 | let view = ShowLessAndClearView()
21 | return view
22 | }()
23 |
24 | var groupName: String? {
25 | didSet {
26 | groupNameLabel.text = groupName
27 | }
28 | }
29 |
30 | var showLessAction: (() -> Void)? {
31 | didSet {
32 | showLessAndClearView.showLessAction = showLessAction
33 | }
34 | }
35 |
36 | var clearAction: (() -> Void)? {
37 | didSet {
38 | showLessAndClearView.clearAction = clearAction
39 | }
40 | }
41 |
42 | init() {
43 | super.init(frame: .zero)
44 | addSubview(groupNameLabel)
45 | addSubview(showLessAndClearView)
46 |
47 | groupNameLabel.snp.makeConstraints { make in
48 | make.left.equalTo(8)
49 | make.top.equalTo(10)
50 | make.bottom.equalTo(-10)
51 | }
52 | showLessAndClearView.snp.makeConstraints { make in
53 | make.right.equalToSuperview()
54 | make.centerY.equalTo(groupNameLabel)
55 | }
56 |
57 | self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap)))
58 | }
59 |
60 | @available(*, unavailable)
61 | required init?(coder: NSCoder) {
62 | fatalError("init(coder:) has not been implemented")
63 | }
64 |
65 | @objc func tap() {
66 | showLessAction?()
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/View/MessageList/MessageGroupMoreView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MessageGroupMoreView.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 12/25/24.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MessageGroupMoreView: UIView {
12 | private let moreLabel: UILabel = {
13 | let label = UILabel()
14 | label.textColor = BKColor.grey.darken3
15 | label.font = UIFont.preferredFont(ofSize: 12)
16 | return label
17 | }()
18 |
19 | let arrowImageView: UIImageView = {
20 | let imageView = UIImageView()
21 | imageView.image = UIImage(named: "keyboard_arrow_right_symbol")?.withRenderingMode(.alwaysTemplate)
22 | imageView.tintColor = BKColor.grey.darken2
23 | return imageView
24 | }()
25 |
26 | var count: Int = 0 {
27 | didSet {
28 | moreLabel.text = NSLocalizedString("viewAllMessages").format(count)
29 | }
30 | }
31 |
32 | init() {
33 | super.init(frame: CGRect.zero)
34 | self.backgroundColor = BKColor.grey.lighten5
35 | self.layer.cornerRadius = 28 / 2
36 | self.clipsToBounds = true
37 |
38 | self.addSubview(moreLabel)
39 | self.addSubview(arrowImageView)
40 | moreLabel.snp.makeConstraints { make in
41 | make.left.equalToSuperview().offset(8)
42 | make.height.equalTo(28).priority(.medium)
43 | make.top.bottom.equalToSuperview()
44 | }
45 | arrowImageView.snp.makeConstraints { make in
46 | make.right.equalToSuperview().offset(-6)
47 | make.centerY.equalToSuperview()
48 | make.left.equalTo(moreLabel.snp.right).offset(4)
49 | }
50 | }
51 |
52 | @available(*, unavailable)
53 | required init?(coder: NSCoder) {
54 | fatalError("init(coder:) has not been implemented")
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/View/MessageSettingFooter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MessageSettingFooter.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 11/14/24.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MessageSettingFooter: UITextView, UITextViewDelegate {
12 | init() {
13 | super.init(frame: CGRect(x: 0, y: 0, width: 0, height: 80), textContainer: .none)
14 | self.backgroundColor = UIColor.clear
15 | self.isEditable = false
16 | self.delegate = self
17 |
18 | // 版本号
19 | let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
20 | // build号
21 | let buildVersion = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? ""
22 |
23 | let attr = NSMutableAttributedString(string: "\(NSLocalizedString("version")) \(appVersion) (\(buildVersion))\n", attributes: [.font: UIFont.preferredFont(ofSize: 12), .foregroundColor: BKColor.grey.darken1])
24 | attr.append(NSAttributedString(string: NSLocalizedString("privacyPolicy"), attributes: [.link: "privacyPolicy"]))
25 | attr.append(NSAttributedString(string: " · "))
26 | attr.append(NSAttributedString(string: NSLocalizedString("userAgreement"), attributes: [.link: "userAgreement"]))
27 | attr.append(NSAttributedString(string: " · "))
28 | attr.append(NSAttributedString(string: NSLocalizedString("restoreSubscription"), attributes: [.link: "restoreSubscription"]))
29 |
30 | let style = NSMutableParagraphStyle()
31 | style.lineSpacing = 6
32 | attr.addAttribute(.paragraphStyle, value: style, range: NSRange(location: 0, length: attr.length))
33 |
34 | self.attributedText = attr
35 | self.linkTextAttributes = [.foregroundColor: BKColor.grey.darken1, .underlineStyle: NSUnderlineStyle.single.rawValue, .font: UIFont.preferredFont(ofSize: 12)]
36 | self.textAlignment = .center
37 | }
38 |
39 | @available(*, unavailable)
40 | required init?(coder: NSCoder) {
41 | fatalError("init(coder:) has not been implemented")
42 | }
43 |
44 | var openLinkHandler: ((String) -> Void)?
45 | func textView(_ textView: UITextView, shouldInteractWith url: URL, in characterRange: NSRange) -> Bool {
46 | self.openLinkHandler?(url.absoluteString)
47 | return false
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/View/MutableTextCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DeviceTokenCell.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2022/3/23.
6 | // Copyright © 2022 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MutableTextCell: BaseTableViewCell {
12 |
13 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
14 | super.init(style: UITableViewCell.CellStyle.value1, reuseIdentifier: reuseIdentifier)
15 | self.selectionStyle = .none
16 | self.accessoryType = .none
17 | self.backgroundColor = BKColor.background.secondary
18 | self.detailTextLabel?.textColor = BKColor.grey.darken2
19 | }
20 |
21 | @available(*, unavailable)
22 | required init?(coder aDecoder: NSCoder) {
23 | fatalError("init(coder:) has not been implemented")
24 | }
25 |
26 | override func bindViewModel(model: MutableTextCellViewModel) {
27 | super.bindViewModel(model: model)
28 |
29 | self.textLabel?.text = model.title
30 | model.text
31 | .drive(self.detailTextLabel!.rx.text)
32 | .disposed(by: rx.reuseBag)
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/View/MutableTextCellViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DeviceTokenCellViewModel.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2022/3/23.
6 | // Copyright © 2022 Fin. All rights reserved.
7 | //
8 |
9 | import RxCocoa
10 | import UIKit
11 | class MutableTextCellViewModel: ViewModel {
12 | var title: String
13 | var text: Driver
14 | init(title: String, text: Driver) {
15 | self.title = title
16 | self.text = text
17 | super.init()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/View/ServerListTableViewCellViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ServerListTableViewCellViewModel.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2022/4/1.
6 | // Copyright © 2022 Fin. All rights reserved.
7 | //
8 |
9 | import RxRelay
10 | import UIKit
11 |
12 | class ServerListTableViewCellViewModel: ViewModel {
13 | let server: Server
14 |
15 | let name: BehaviorRelay
16 | let key: BehaviorRelay
17 | let state: BehaviorRelay
18 |
19 | init(server: Server) {
20 | self.server = server
21 |
22 | self.name = BehaviorRelay(value: {
23 | var serverName = URL(string: server.address)?.host ?? "Invalid Server"
24 | if let name = server.name, !name.isEmpty {
25 | serverName = name + "\n" + serverName
26 | }
27 | return serverName
28 | }())
29 | self.key = BehaviorRelay(value: !server.key.isEmpty ? server.key : "none")
30 | self.state = BehaviorRelay(value: server.state == .ok)
31 |
32 | super.init()
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/View/SettingSectionHeader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SettingSectionHeader.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 11/13/24.
6 | // Copyright © 2024 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SettingSectionHeader: UIView {
12 | let titleLabel: UILabel = {
13 | let label = UILabel()
14 | label.textColor = BKColor.grey.darken1
15 | label.font = UIFont.preferredFont(ofSize: 12)
16 | label.numberOfLines = 0
17 | return label
18 | }()
19 |
20 | init() {
21 | super.init(frame: CGRect.zero)
22 | self.addSubview(titleLabel)
23 | titleLabel.snp.makeConstraints { make in
24 | make.top.equalTo(12)
25 | make.bottom.equalTo(-12)
26 | make.left.equalTo(13)
27 | make.right.equalTo(-13)
28 | }
29 | }
30 |
31 | @available(*, unavailable)
32 | required init?(coder: NSCoder) {
33 | fatalError("init(coder:) has not been implemented")
34 | }
35 | }
36 |
37 | class SettingSectionFooter: UIView {
38 | let titleLabel: UILabel = {
39 | let label = UILabel()
40 | label.textColor = BKColor.grey.darken1
41 | label.font = UIFont.preferredFont(ofSize: 12)
42 | label.numberOfLines = 0
43 | return label
44 | }()
45 |
46 | init() {
47 | super.init(frame: CGRect.zero)
48 | self.addSubview(titleLabel)
49 | titleLabel.snp.makeConstraints { make in
50 | make.top.equalTo(8)
51 | // make.bottom.equalTo(-6)
52 | make.left.equalTo(12)
53 | make.right.equalTo(-12)
54 | }
55 | }
56 |
57 | @available(*, unavailable)
58 | required init?(coder: NSCoder) {
59 | fatalError("init(coder:) has not been implemented")
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/View/SoundCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCell.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/9/14.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import AVKit
10 | import Material
11 | import UIKit
12 |
13 | class SoundCell: BaseTableViewCell {
14 | let copyButton = IconButton(image: UIImage(named: "baseline_file_copy_white_24pt"), tintColor: BKColor.grey.base)
15 | let nameLabel: UILabel = {
16 | let label = UILabel()
17 | label.fontSize = 14
18 | label.textColor = BKColor.grey.darken4
19 | return label
20 | }()
21 |
22 | let durationLabel: UILabel = {
23 | let label = UILabel()
24 | label.fontSize = 12
25 | label.textColor = BKColor.grey.darken1
26 | return label
27 | }()
28 |
29 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
30 | super.init(style: style, reuseIdentifier: reuseIdentifier)
31 | self.selectionStyle = .none
32 | self.backgroundColor = BKColor.background.secondary
33 | self.contentView.addSubview(nameLabel)
34 | self.contentView.addSubview(durationLabel)
35 | self.contentView.addSubview(copyButton)
36 |
37 | nameLabel.snp.makeConstraints { make in
38 | make.left.top.equalToSuperview().offset(15)
39 | }
40 | durationLabel.snp.makeConstraints { make in
41 | make.left.equalTo(nameLabel)
42 | make.top.equalTo(nameLabel.snp.bottom).offset(5)
43 | make.bottom.equalToSuperview().offset(-15)
44 | }
45 | copyButton.snp.makeConstraints { make in
46 | make.right.equalToSuperview().offset(-15)
47 | make.centerY.equalToSuperview()
48 | make.width.height.equalTo(40)
49 | }
50 | }
51 |
52 | @available(*, unavailable)
53 | required init?(coder aDecoder: NSCoder) {
54 | fatalError("init(coder:) has not been implemented")
55 | }
56 |
57 | override func bindViewModel(model: SoundCellViewModel) {
58 | super.bindViewModel(model: model)
59 |
60 | model.name
61 | .bind(to: nameLabel.rx.text)
62 | .disposed(by: rx.reuseBag)
63 | model.duration
64 | .map { String(format: "%.2g second(s)", CMTimeGetSeconds($0)) }
65 | .bind(to: durationLabel.rx.text)
66 | .disposed(by: rx.reuseBag)
67 |
68 | copyButton.rx.tap
69 | .map { model.name.value }
70 | .bind(to: model.copyNameAction)
71 | .disposed(by: rx.reuseBag)
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/View/SoundCellViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCellViewModel.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/11/17.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import AVKit
10 | import Foundation
11 | import RxCocoa
12 | import RxSwift
13 |
14 | class SoundCellViewModel: ViewModel {
15 | let name = BehaviorRelay(value: "")
16 | let duration = BehaviorRelay(value: .zero)
17 |
18 | let copyNameAction = PublishRelay()
19 | let playAction = PublishRelay()
20 |
21 | let model: AVURLAsset
22 | init(model: AVURLAsset) {
23 | self.model = model
24 | name.accept(model.url.deletingPathExtension().lastPathComponent)
25 | duration.accept(model.duration)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/View/SpacerCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SpacerCell.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2021/6/25.
6 | // Copyright © 2021 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SpacerCell: UITableViewCell {
12 | var height: CGFloat = 0 {
13 | didSet {
14 | self.contentView.snp.remakeConstraints { make in
15 | make.height.equalTo(height)
16 | }
17 | }
18 | }
19 |
20 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
21 | super.init(style: style, reuseIdentifier: reuseIdentifier)
22 | self.backgroundColor = UIColor.clear
23 | self.selectionStyle = .none
24 | }
25 |
26 | @available(*, unavailable)
27 | required init?(coder aDecoder: NSCoder) {
28 | fatalError("init(coder:) has not been implemented")
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/View/TextCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextCell.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2021/6/25.
6 | // Copyright © 2021 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class DetailTextCell: UITableViewCell {
12 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
13 | super.init(style: .value1, reuseIdentifier: reuseIdentifier)
14 | self.selectionStyle = .none
15 | self.accessoryType = .disclosureIndicator
16 | self.backgroundColor = BKColor.background.secondary
17 | }
18 |
19 | @available(*, unavailable)
20 | required init?(coder aDecoder: NSCoder) {
21 | fatalError("init(coder:) has not been implemented")
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/View/UINavigationItem+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UINavigationItem+Extension.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/9/23.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // 如果第一个 item 是系统自带的 UIBarButtonItem ,则距离导航栏左右距离只有8
12 | // 自己定义的的则最少有16,太宽了
13 | // 所以先用 一个 fixedSpace UIBarButtonItem 先把距离给缩短点,
14 | // 然后用个 AlignmentRectInsetsOverridable 把自己的按钮往 左/右 挪动,减少距离
15 | // 用 HitTestSlopable 增加点击区域
16 | enum UINavigationItemPosition {
17 | case left
18 | case right
19 | }
20 |
21 | extension UINavigationItem {
22 | func setLeftBarButtonItem(item: UIBarButtonItem) {
23 | setBarButtonItems(items: [item], position: .left)
24 | }
25 |
26 | func setRightBarButtonItem(item: UIBarButtonItem) {
27 | setBarButtonItems(items: [item], position: .right)
28 | }
29 |
30 | func setBarButtonItems(items: [UIBarButtonItem], position: UINavigationItemPosition) {
31 | guard items.count > 0 else {
32 | self.leftBarButtonItems = nil
33 | return
34 | }
35 | var buttonItems = items
36 | if #available(iOS 11.0, *) {
37 | buttonItems.forEach { item in
38 | guard let view = item.customView else { return }
39 | item.customView?.translatesAutoresizingMaskIntoConstraints = false
40 | (item.customView as? HitTestSlopable)?.hitTestSlop = UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10)
41 | (item.customView as? AlignmentRectInsetsOverridable)?.alignmentRectInsetsOverride = UIEdgeInsets(top: 0, left: position == .left ? 8 : -8, bottom: 0, right: position == .left ? -8 : 8)
42 | item.customView?.snp.makeConstraints { make in
43 | make.width.equalTo(view.bounds.size.width > 24 ? view.bounds.width : 24)
44 | make.height.equalTo(view.bounds.size.height > 24 ? view.bounds.height : 24)
45 | }
46 | }
47 | buttonItems.insert(UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil), at: 0)
48 | }
49 | else {
50 | let spacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
51 | spacer.width = -8
52 | buttonItems.insert(spacer, at: 0)
53 | }
54 | if position == .left {
55 | self.leftBarButtonItems = buttonItems
56 | }
57 | else {
58 | self.rightBarButtonItems = buttonItems
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/View/iCloudStatusCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // iCloudStatusCell.swift
3 | // Bark
4 | //
5 | // Created by huangfeng on 2020/5/29.
6 | // Copyright © 2020 Fin. All rights reserved.
7 | //
8 |
9 | import CloudKit
10 | import UIKit
11 |
12 | class iCloudStatusCell: UITableViewCell {
13 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
14 | super.init(style: .value1, reuseIdentifier: reuseIdentifier)
15 | self.selectionStyle = .none
16 | self.backgroundColor = BKColor.background.secondary
17 | self.textLabel?.text = NSLocalizedString("iCloudSatatus")
18 | self.detailTextLabel?.text = ""
19 | self.detailTextLabel?.textColor = BKColor.grey.darken2
20 | CKContainer.default().accountStatus { status, _ in
21 | dispatch_sync_safely_main_queue {
22 | switch status {
23 | case .available:
24 | self.detailTextLabel?.text = NSLocalizedString("available")
25 | case .noAccount, .restricted, .temporarilyUnavailable:
26 | self.detailTextLabel?.text = NSLocalizedString("restricted")
27 | case .couldNotDetermine:
28 | self.detailTextLabel?.text = NSLocalizedString("unknown")
29 | @unknown default:
30 | break
31 | }
32 | }
33 | }
34 | }
35 |
36 | @available(*, unavailable)
37 | required init?(coder aDecoder: NSCoder) {
38 | fatalError("init(coder:) has not been implemented")
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | bark.day.app
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 |
2 | ### Bark
3 | - 免费、轻量!简单调用接口即可给自己的iPhone发送推送。
4 | - 依赖苹果APNs,及时、稳定、可靠
5 | - 不会消耗设备的电量, 基于系统推送服务与推送扩展,APP本体并不需要运行。
6 | - 隐私安全,可以通过一些方式确保包含作者本人在内的所有人都无法窃取你的隐私。 *点击详细了解如何保障[隐私安全](/privacy)*
7 |
8 | ### 源码
9 | - [Bark](https://github.com/Finb/Bark) 是完整开源的 iOS APP,用来接收自定义推送。
10 | - [bark-server](https://github.com/Finb/bark-server) 是完整开源的 Bark 服务后端,用来接收用户的推送请求并转发给苹果APNS。
11 |
12 | ### 反馈
13 | - [Bark 问题反馈群](https://t.me/joinchat/OsCbLzovUAE0YjY1) (注意点击入群验证)
14 | - [GitHub Issues](https://github.com/Finb/Bark/issues)
15 |
16 | ### 免费
17 | Bark **2018年7月**上线,至少会维持运营到 **2031年7月** 。*(说不出口“永久”这个词,后续还有需求再续吧)*
18 | APP在维持期间,不会有任何形式的收费功能与广告,各位彦祖放心使用。
19 |
20 | ### 赞助
21 | 目前接收 GitHub 赞助、App内内购赞助。非常感谢每一位赞助者!
22 | 赞助者:[https://github.com/sponsors/Finb](https://github.com/sponsors/Finb)
23 |
24 | ### 文档
25 | - **App**
26 | - [使用教程](/tutorial)
27 | - [推送加密](/encryption)
28 | - [常见问题](/faq)
29 | - **服务端**
30 | - [部署服务](/deploy)
31 | - [批量推送](/batch)
32 | - [编译代码](/build)
33 | - [推送证书](/cert)
34 | - [隐私安全](/privacy)
--------------------------------------------------------------------------------
/docs/_coverpage.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Bark
4 |
5 | > 一款注重隐私、安全可控的自定义通知推送工具。
6 |
7 | - 免费、简单、安全
8 | - 打开即用
9 |
10 | [GitHub](https://github.com/finb/bark)
11 | [Get Started](#bark)
12 |
--------------------------------------------------------------------------------
/docs/_media/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/docs/_media/Icon.png
--------------------------------------------------------------------------------
/docs/_media/environment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/docs/_media/environment.png
--------------------------------------------------------------------------------
/docs/_media/example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/docs/_media/example.jpg
--------------------------------------------------------------------------------
/docs/_media/shortcuts_cn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Finb/Bark/c1d9dfe7f663bfc31f5d01881220915b251c2002/docs/_media/shortcuts_cn.png
--------------------------------------------------------------------------------
/docs/_navbar.md:
--------------------------------------------------------------------------------
1 | * Translations
2 | - [:cn: 简体中文](/)
3 | - [:uk: English](/en-us/)
--------------------------------------------------------------------------------
/docs/_sidebar.md:
--------------------------------------------------------------------------------
1 | - [Bark](/#bark)
2 | - **App**
3 | - [使用教程](/tutorial)
4 | - [推送加密](/encryption)
5 | - [常见问题](/faq)
6 | - **服务端**
7 | - [部署服务](/deploy)
8 | - [批量推送](/batch)
9 | - [编译代码](/build)
10 | - [推送证书](/cert)
11 | - [隐私安全](/privacy)
--------------------------------------------------------------------------------
/docs/batch.md:
--------------------------------------------------------------------------------
1 |
2 | ### 个人用户
3 | 批量推送仅支持Json请求,需 bark-server 更新至 v2.1.9。([https://api.day.app](https://api.day.app) 暂时不会更新至 v2.1.9, 目前还不支持批量推送)
4 | 用法:
5 | ```sh
6 | curl -X "POST" "https://api.day.app/push" \
7 | -H 'Content-Type: application/json; charset=utf-8' \
8 | -d $'{
9 | "title": "Title",
10 | "body": "Body",
11 | "sound": "minuet",
12 | "group": "test",
13 | "device_keys": ["key1", "key2", ... ]
14 | }'
15 | ```
16 |
17 | ### 中间服务
18 | 如果你的服务需要大批量且及时地向用户发送推送,建议自建服务端。可以提供 Url Scheme 方便用户一键更改服务器。
19 |
20 | Url Scheme 示例:
21 | ```
22 | bark://addServer?address=https%3A%2F%2Fapi.day.app
23 | ```
24 | bark-server 对配置要求很低,以下是美西 VPS 各配置下的 QPS 测试结果 :
25 |
26 | | Cores | Ram | Speed |
27 | | ----- | ----------- |----------- |
28 | | 1 | 3.75 gb |4,023 p/sec |
29 | | 4 | 16 gb |21,413 p/sec |
30 | | 16 | 64 gb |64,516 p/sec |
31 | | 64 | 256 gb |105,263 p/sec |
32 |
33 | 若 QPS 不高于 200,可继续使用公共服务([https://api.day.app](https://api.day.app))。
34 | 若 QPS 超过 200,推荐自建服务端,未来在公共服务器负载过高时,可能会引入流量限制(目前尚未限制)。
35 | 若 QPS 超过 3000,尽量自建服务端,部署时添加 `--max-apns-client-count` 参数,详情请查看[部署文档](/deploy)
--------------------------------------------------------------------------------
/docs/build.md:
--------------------------------------------------------------------------------
1 | ## 下载源码
2 | 从GitHub下载源码 [bark-server](https://github.com/Finb/bark-server)
3 |
4 | 或
5 | ```sh
6 | git clone https://github.com/Finb/bark-server.git
7 | ```
8 | ## 配置依赖
9 | - Golang 1.18+
10 | - Go Mod (env GO111MODULE=on)
11 | - Go Mod Proxy (env GOPROXY=https://goproxy.cn)
12 | - 安装 [go-task](https://taskfile.dev/installation/)
13 |
14 | ## 交叉编译所有平台
15 | ```sh
16 | task
17 | ```
18 |
19 | ## 编译指定平台
20 | ```sh
21 | task linux_amd64
22 | task linux_amd64_v3
23 | ```
24 |
25 | ## 支持的平台
26 |
27 | - linux_386
28 | - linux_amd64
29 | - linux_amd64_v2
30 | - linux_amd64_v3
31 | - linux_amd64_v4
32 | - linux_armv5
33 | - linux_armv6
34 | - linux_armv7
35 | - linux_armv8
36 | - linux_mips_hardfloat
37 | - linux_mipsle_softfloat
38 | - linux_mipsle_hardfloat
39 | - linux_mips64
40 | - linux_mips64le
41 | - windows_386.exe
42 | - windows_amd64.exe
43 | - windows_amd64_v2.exe
44 | - windows_amd64_v3.exe
45 | - windows_amd64_v4.exe
46 | - darwin_amd64
47 | - darwin_arm64
--------------------------------------------------------------------------------
/docs/cert.md:
--------------------------------------------------------------------------------
1 | 当你需要集成Bark到自己的系统或重新实现后端代码时可能需要推送证书
2 |
3 | ##### 有效期到: *永久*
4 | ##### Key ID:*LH4T9V5U4R*
5 | ##### TeamID:*5U8LBRXG3A*
6 | ##### 下载地址:[AuthKey_LH4T9V5U4R_5U8LBRXG3A.p8](https://github.com/Finb/bark-server/releases/download/v1.0.2/AuthKey_LH4T9V5U4R_5U8LBRXG3A.p8)
--------------------------------------------------------------------------------
/docs/en-us/README.md:
--------------------------------------------------------------------------------
1 |
2 | ### Bark
3 | - Free, lightweight! Simply call the interface to send push notifications to your own iPhone.
4 | - Depends on Apple APNs, timely, stable and reliable
5 | - Does not consume device’s battery power. Based on system push service and push extension, APP itself does not need to run.
6 | - Privacy and security. You can ensure that no one, including the author himself, can steal your privacy through some ways. *Click for details on how to ensure [privacy and security](/en-us/privacy)*
7 |
8 | ### Source code
9 | - [Bark](https://github.com/Finb/Bark) is a fully open source iOS APP for receiving custom push notifications
10 | - [bark-server](https://github.com/Finb/bark-server) is a fully open source Bark service backend for receiving user push requests and forwarding them to Apple APNS.
11 |
12 | ### Feedback
13 | - [Telegram Group](https://t.me/joinchat/OsCbLzovUAE0YjY1) (Note: click verification to join group)
14 | - [GitHub Issues](https://github.com/Finb/Bark/issues)
15 |
16 | ### Free
17 | Bark was launched in **July 2018** and will maintain operation until at least **July 2031**. *(Can’t say the word “permanent”, let’s renew it later if there is still demand)*
18 | APP will not have any form of charge or advertisement during maintenance period. Feel free to use it.
19 |
20 | ### Sponsorship
21 | Currently only accept GitHub sponsorship. Thank you very much for every sponsor
22 | Sponsors:[https://github.com/sponsors/Finb](https://github.com/sponsors/Finb)
23 |
24 | ### Documentation
25 | - **App**
26 | - [Tutorial](/en-us/tutorial)
27 | - [Encryption](/en-us/encryption)
28 | - [FAQs](/en-us/faq)
29 | - **Server**
30 | - [Deploy](/en-us/deploy)
31 | - [Batch Push](/en-us/batch)
32 | - [Build](/en-us/build)
33 | - [Certificate](/en-us/cert)
34 | - [Privacy](/en-us/privacy)
--------------------------------------------------------------------------------
/docs/en-us/_coverpage.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Bark
4 |
5 | > A privacy-focused, secure and controllable custom notification push tool.
6 |
7 | - Free, simple and safe
8 | - Open and go
9 |
10 | [GitHub](https://github.com/finb/bark)
11 | [Get Started](#bark)
12 |
--------------------------------------------------------------------------------
/docs/en-us/_sidebar.md:
--------------------------------------------------------------------------------
1 | - [Bark](/en-us/#bark)
2 | - **App**
3 | - [Tutorial](/en-us/tutorial)
4 | - [Encryption](/en-us/encryption)
5 | - [FAQs](/en-us/faq)
6 | - **Server**
7 | - [Deploy](/en-us/deploy)
8 | - [Batch Push](/en-us/batch)
9 | - [Build](/en-us/build)
10 | - [Certificate](/en-us/cert)
11 | - [Privacy](/en-us/privacy)
--------------------------------------------------------------------------------
/docs/en-us/batch.md:
--------------------------------------------------------------------------------
1 |
2 | ### Individual Users
3 | Batch push is only supported with Json requests, and bark-server needs to be updated to v2.1.9. ([https://api.day.app](https://api.day.app) will not be updated to v2.1.9 for now, and currently does not support batch push.)
4 | Usage:
5 | ```sh
6 | curl -X "POST" "https://api.day.app/push" \
7 | -H 'Content-Type: application/json; charset=utf-8' \
8 | -d $'{
9 | "title": "Title",
10 | "body": "Body",
11 | "sound": "minuet",
12 | "group": "test",
13 | "device_keys": ["key1", "key2", ... ]
14 | }'
15 | ```
16 |
17 | ### Middleware Services
18 | If your service requires sending large volumes of push notifications to users in a timely manner, it is recommended to set up your own server. You can provide a Url Scheme to allow users to change the server with one click.
19 |
20 | Url Scheme Example:
21 | ```
22 | bark://addServer?address=https%3A%2F%2Fapi.day.app
23 | ```
24 | bark-server has very low configuration requirements. Below are the QPS test results for various configurations on a US West VPS:
25 |
26 | | Cores | Ram | Speed |
27 | | ----- | ----------- |----------- |
28 | | 1 | 3.75 gb |4,023 p/sec |
29 | | 4 | 16 gb |21,413 p/sec |
30 | | 16 | 64 gb |64,516 p/sec |
31 | | 64 | 256 gb |105,263 p/sec |
32 |
33 | If QPS does not exceed 200, you can continue to use the public service([https://api.day.app](https://api.day.app))。
34 | If QPS exceeds 200, it is recommended to set up your own server. In the future, when the public server is under high load, traffic restrictions may be introduced (currently, there are no restrictions).
35 | If QPS exceeds 3000, it is strongly recommended to set up your own server and add the --max-apns-client-count parameter during deployment. For details, refer to the[Deployment Documentation.](/en-us/deploy)
--------------------------------------------------------------------------------
/docs/en-us/build.md:
--------------------------------------------------------------------------------
1 | ## Download Source Code
2 | Download the source code from GitHub [bark-server](https://github.com/Finb/bark-server)
3 |
4 | or
5 | ```sh
6 | git clone https://github.com/Finb/bark-server.git
7 | ```
8 | ## Configure Dependencies
9 | - Golang 1.18+
10 | - Go Mod (env GO111MODULE=on)
11 | - Go Mod Proxy (env GOPROXY=https://goproxy.cn)
12 | - Install [go-task](https://taskfile.dev/installation/)
13 |
14 | ## Cross-Compile for All Platforms
15 | ```sh
16 | task
17 | ```
18 |
19 | ## Compile for Specific Platforms
20 | ```sh
21 | task linux_amd64
22 | task linux_amd64_v3
23 | ```
24 |
25 | ## Supported Platforms
26 |
27 | - linux_386
28 | - linux_amd64
29 | - linux_amd64_v2
30 | - linux_amd64_v3
31 | - linux_amd64_v4
32 | - linux_armv5
33 | - linux_armv6
34 | - linux_armv7
35 | - linux_armv8
36 | - linux_mips_hardfloat
37 | - linux_mipsle_softfloat
38 | - linux_mipsle_hardfloat
39 | - linux_mips64
40 | - linux_mips64le
41 | - windows_386.exe
42 | - windows_amd64.exe
43 | - windows_amd64_v2.exe
44 | - windows_amd64_v3.exe
45 | - windows_amd64_v4.exe
46 | - darwin_amd64
47 | - darwin_arm64
--------------------------------------------------------------------------------
/docs/en-us/cert.md:
--------------------------------------------------------------------------------
1 | When you need to integrate Bark into your own system or re-implement the backend code, you may need to push certificates.
2 |
3 | ##### Valid Until: *Permanent*
4 | ##### Key ID: *LH4T9V5U4R*
5 | ##### Team ID: *5U8LBRXG3A*
6 | ##### Download Link: [AuthKey_LH4T9V5U4R_5U8LBRXG3A.p8](https://github.com/Finb/bark-server/releases/download/v1.0.2/AuthKey_LH4T9V5U4R_5U8LBRXG3A.p8)
--------------------------------------------------------------------------------
/docs/en-us/encryption.md:
--------------------------------------------------------------------------------
1 | #### What is push encryption
2 | Push encryption is a method to protect the push content, which uses a custom key to encrypt and decrypt the push content when sending and receiving. In this way, the push content will not be obtained or leaked by Bark server and Apple APNs server during transmission.
3 |
4 | #### Set custom key
5 | 1. Open APP homepage
6 | 2. Find “Push Encryption”, click Encryption Settings
7 | 3. Select encryption algorithm, fill in KEY as required, click Done to save custom key
8 |
9 | #### Send encrypted push
10 | To send an encrypted push, you need to first convert the Bark request parameters into a json format string, then use the previously set key and corresponding algorithm to encrypt the string, and finally send the encrypted ciphertext as ciphertext parameter to the server.
11 | **For example:**
12 | ```sh
13 | #!/usr/bin/env bash
14 |
15 | set -e
16 |
17 | # bark key
18 | deviceKey='F5u42Bd3HyW8KxkUqo2gRA'
19 | # push payload
20 | json='{"body": "test", "sound": "birdsong"}'
21 |
22 | # must be 16 bit long
23 | key='1234567890123456'
24 | iv='1111111111111111'
25 |
26 | # openssl requires Hex encoding of manual keys and IVs, not ASCII encoding.
27 | key=$(printf $key | xxd -ps -c 200)
28 | iv=$(printf $iv | xxd -ps -c 200)
29 |
30 | ciphertext=$(echo -n $json | openssl enc -aes-128-cbc -K $key -iv $iv | base64)
31 |
32 | # The console will print "d3QhjQjP5majvNt5CjsvFWwqqj2gKl96RFj5OO+u6ynTt7lkyigDYNA3abnnCLpr"
33 | echo $ciphertext
34 |
35 | curl --data-urlencode "ciphertext=$ciphertext" http://api.day.app/$deviceKey
36 | ```
37 |
--------------------------------------------------------------------------------
/docs/en-us/privacy.md:
--------------------------------------------------------------------------------
1 | #### How Privacy Can Be Leaked
2 | The route a push notification takes from sending to receiving is as follows:
3 | Sender → Server① → Apple APNS Server → Your Device → Bark APP② .
4 |
5 | The two red-marked areas are potential points of privacy leakage
6 | * The sender does not use HTTPS or uses a public server*(the author can see the request logs)*
7 | * The Bark App itself is insecure, and the version uploaded to the App Store has been modified.
8 |
9 | #### Solving Server-Side Privacy Issues
10 | * You can use the open-source backend code to [ deploy your own backend service ](/en-us/deploy.md) and enable HTTPS.
11 | * Use [encrypted push](/en-us/encryption) with a custom key to encrypt the push content.
12 |
13 | #### Ensuring the App is Completely Built from Open-Source Code
14 | To ensure that the App is secure and has not been modified by anyone (including the author), Bark is built by GitHub Actions and then uploaded to the App Store.
15 | Within the Bark app settings, you can view the GitHub Run Id. Clicking on it will allow you to find the configuration files used for the current version's build, the source code at compile time, the build number of the version uploaded to the App Store, and more.
16 |
17 |
18 | The same build number can only be uploaded to the App Store once, making this number unique.
19 | You can use this number to compare with the Bark App downloaded from the store. If they match, it proves that the App downloaded from the App Store is completely built from open-source code.
20 |
21 | Example: Bark 1.2.9 - 3
22 | https://github.com/Finb/Bark/actions/runs/3327969456
23 |
24 | 1. Find the commit id at compile time to view the complete source code at compile time.
25 | 2. Check .github/workflows/testflight.yaml to verify all Actions and ensure that the logs printed by the Actions have not been tampered with.
26 | 3. View Action Logs https://github.com/Finb/Bark/actions/runs/3327969456/jobs/5503414528
27 | 4. Find the packaged App ID, Team ID, version, and build number uploaded to the App Store, among other information.
28 | 5. Download the corresponding version ipa from the store and compare whether the build number matches the one in the logs*(this number is unique for the same APP, and once successfully uploaded, it cannot be uploaded again with the same version build number)*
29 |
30 |
31 | *Here, we do not consider whether iOS leaks privacy.*
--------------------------------------------------------------------------------
/docs/encryption.md:
--------------------------------------------------------------------------------
1 | #### 什么是推送加密
2 | 推送加密是一种保护推送内容的方法,它使用自定义秘钥在发送和接收时对推送内容进行加密和解密。 这样,推送内容在传输过程中就不会被 Bark 服务器和苹果 APNs 服务器获取或泄露。
3 |
4 | #### 设置自定义秘钥
5 | 1. 打开APP首页
6 | 2. 找到 “推送加密” ,点击加密设置
7 | 3. 选择加密算法,按要求填写KEY,点击完成保存自定义秘钥
8 |
9 | #### 发送加密推送
10 | 要发送加密推送,首先需要把 Bark 请求参数转换成 json 格式的字符串,然后用之前设置的秘钥和相应的算法对字符串进行加密,最后把加密后的密文作为ciphertext参数发送到服务器。
11 | **示例:**
12 | ```sh
13 | #!/usr/bin/env bash
14 |
15 | set -e
16 |
17 | # bark key
18 | deviceKey='F5u42Bd3HyW8KxkUqo2gRA'
19 | # push payload
20 | json='{"body": "test", "sound": "birdsong"}'
21 |
22 | # Must be 16 bit long
23 | key='1234567890123456'
24 | # IV can be randomly generated, but if it is random, it needs to be passed in the iv parameter.
25 | iv='1234567890123456'
26 |
27 | # openssl requires Hex encoding of manual keys and IVs, not ASCII encoding.
28 | key=$(printf $key | xxd -ps -c 200)
29 | iv=$(printf $iv | xxd -ps -c 200)
30 |
31 | ciphertext=$(echo -n $json | openssl enc -aes-128-cbc -K $key -iv $iv | base64)
32 |
33 | # The console will print "+aPt5cwN9GbTLLSFri60l3h1X00u/9j1FENfWiTxhNHVLGU+XoJ15JJG5W/d/yf0"
34 | echo $ciphertext
35 |
36 | # URL encoding the ciphertext, there may be special characters.
37 | curl --data-urlencode "ciphertext=$ciphertext" --data-urlencode "iv=1234567890123456" https://api.day.app/$deviceKey
38 | ```
--------------------------------------------------------------------------------
/docs/faq.md:
--------------------------------------------------------------------------------
1 | #### 无法收到推送
2 | 在 App 设置中检查 Device Token 是否正常。如果不正常,参考 [这里](#DeviceToken显示未知)
3 | 如果正常,可以重启下设备,如果还不能接收到推送,检查推送请求返回状态码是否为 code 200。
4 | 排查都正常后还有问题可在[Bark 问题反馈群](https://t.me/joinchat/OsCbLzovUAE0YjY1)反馈。
5 |
6 | #### DeviceToken显示未知
7 | 这很有可能是设备没有正常连接到苹果服务器,伴随发生 iMessage 不可用、其他 App 推送也收不到等问题。
8 | 可以尝试切换网络、重启手机、如果翻墙代理了 Apple 服务可以关闭翻墙工具。
9 | 此问题是用户设备与苹果服务器的连接问题,作者并不能提供任何帮助,需自己尝试解决。
10 |
11 | #### 推送使用次数限制
12 | 正常请求(HTTP状态码为200)无任何限制。
13 | 但如果在5分钟内超过1000次错误请求(HTTP状态码为400 404 500)IP会被 BAN 24小时
14 |
15 | #### 莫名收到未知推送,比如 NoContent
16 | 可能的原因:
17 | 1. 如果用 Safari 发送过推送,在Safari输入任意网址时,可能 Safari 对历史记录搜索进行自动补全时,正好补全成 Bark API 的 URL,然后预加载触发推送。
18 | 2. 如果将 Bark API URL 发送到聊天软件如微信文件传输助手,微信会不定时的请求 URL 触发推送。
19 | 3. 推送 Key 泄露,推荐在服务器列表页面重置 Key。
20 |
21 | #### 提示服务器错误
22 | 偶尔提示一次可以忽略,可能是设备进入后台导致网络请求超时之类的原因导致的。
23 |
24 | #### 时效性通知无效
25 | 可以尝试重启设备 来解决。
26 |
27 | #### 无法保存通知历史,或下拉推送没有点击复制按钮无法复制
28 | 可以尝试重启设备 来解决。
29 | 因某些原因导致推送服务扩展([UNNotificationServiceExtension](https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension))未能正常运行,执行通知保存的代码未能正常执行。
30 |
31 | #### 自动复制推送失效
32 | iOS 14.5 之后的版本因权限收紧,不能在收到推送时自动复制推送内容到剪切板。
33 | 可暂时先下拉推送或在锁屏界面左滑推送点查看即可自动复制,或点击弹出的推送复制按钮。
34 |
35 | #### 默认打开通知历史列表
36 | 再次开启APP时,会跳转到上次打开的页面。
37 | 只需退出APP时,停留在历史消息页面,再次打开APP时就是历史消息页面。
38 |
39 | #### 推送 API 是否支持 POST 请求?
40 | Bark支持 GET POST ,支持使用Json
41 | 无论哪种请求方式,参数名都一样, 参考[使用教程](/tutorial#请求方式)
42 |
43 | #### 推送特殊字符导致推送失败,比如 推送内容包含链接,或推送异常 比如 + 变成空格
44 | 这是因为整个链接不规范导致的问题,常发生在自己手动拼接URL时。
45 | 拼接URL时,注意将参数进行URL编码
46 |
47 | ```sh
48 | # 例如
49 | https://api.day.app/key/{推送内容}
50 |
51 | # 如果{推送内容}是
52 | "a/b/c/"
53 |
54 | # 则最后拼接的URL是
55 | https://api.day.app/key/a/b/c/
56 | # 将找不到对应的路由,后端程序将返回404
57 |
58 | # 应该将 {推送内容} url编码后再进行拼接
59 | https://api.day.app/key/a%2Fb%2Fc%2F
60 | ```
61 | 如果是使用成熟的HTTP库时,参数都会被自动处理,无需自己手动编码。
62 | 但如果是自己去拼接URL时,则需要特别注意参数中的特殊字符,**最好不管有没有特殊字符,无脑套一层URL编码**。
63 |
64 | #### 如何保障隐私安全
65 | 参考[隐私安全](/privacy)
66 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Bark
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/docs/privacy.md:
--------------------------------------------------------------------------------
1 | #### 隐私如何泄露
2 | 一条推送从发送到接收经过路线是:
3 | 发送端 →服务端① → 苹果APNS服务器 → 你的设备 → Bark APP② 。
4 |
5 | 红色的两处地方可能泄露隐私
6 | * 发送端未使用HTTPS或使用公共服务器*(作者会看到请求日志)*
7 | * Bark App 本身不安全,上传到 App Store 的版本经过修改。
8 |
9 | #### 解决服务端隐私问题
10 | * 你可以使用开源的后端代码,自行[部署后端服务](/deploy.md),开启HTTPS。
11 | * 使用自定义秘钥的[加密推送](/encryption) ,加密推送内容
12 |
13 | #### 保证 APP 完全由开源代码构建
14 | 为确保 App 是安全、未经任何人(包含作者)修改过的,Bark 是由 GitHub Actions 构建后上传到 App Store。
15 | Bark应用设置内可以查看到 GitHub Run Id,点击可在里面找到当前版本构建所使用的配置文件、编译时的源代码、上传到 App Store 的版本 build 号 等等信息。
16 |
17 |
18 | 同一个版本 build 号仅能上传到 App Store 一次,所以这个号是唯一的。
19 | 可用此号对比从商店下载的 Bark App,如果一致则证明从 App Store 下载的 App 是完全由开源代码构建。
20 |
21 | 举例: Bark 1.2.9 - 3
22 | https://github.com/Finb/Bark/actions/runs/3327969456
23 |
24 | 1. 找到编译时的 commit id ,可以查看编译时完整的源码
25 | 2. 查看 .github/workflows/testflight.yaml ,验证所有 Action ,确保 Action 打印的日志未被篡改
26 | 3. 查看 Action Logs https://github.com/Finb/Bark/actions/runs/3327969456/jobs/5503414528
27 | 4. 找到 打包的App ID、Team ID、上传到 App Store 的版本与 build 号等信息。
28 | 5. 下载商店对应版本ipa,比对版本build号是否与日志中一致*(这个号码同一个APP是唯一的,成功上传了就不能再以相同的版本build号上传)*
29 |
30 |
31 | *这里不考虑iOS是否泄露隐私*
--------------------------------------------------------------------------------
/fastlane/Appfile:
--------------------------------------------------------------------------------
1 | app_identifier("me.fin.bark") # The bundle identifier of your app
2 | apple_id("finuuid@gmail.com") # Your Apple email address
3 |
4 | itc_team_id("118137723") # App Store Connect Team ID
5 | team_id("5U8LBRXG3A") # Developer Portal Team ID
6 |
7 | # For more information about the Appfile, see:
8 | # https://docs.fastlane.tools/advanced/#appfile
9 |
--------------------------------------------------------------------------------
/fastlane/Fastfile:
--------------------------------------------------------------------------------
1 | # This file contains the fastlane.tools configuration
2 | # You can find the documentation at https://docs.fastlane.tools
3 | #
4 | # For a list of all available actions, check out
5 | #
6 | # https://docs.fastlane.tools/actions
7 | #
8 | # For a list of all available plugins, check out
9 | #
10 | # https://docs.fastlane.tools/plugins/available-plugins
11 | #
12 |
13 | # Uncomment the line if you want fastlane to automatically update itself
14 | # update_fastlane
15 |
16 | default_platform(:ios)
17 |
18 | platform :ios do
19 | desc "Push a new beta build to TestFlight"
20 | lane :beta do | options |
21 | setup_ci
22 |
23 | version = options[:store_version_number]
24 | if !version.nil? && !version.empty?
25 | increment_version_number(version_number: version)
26 | end
27 |
28 | build = options[:build_number]
29 | if !build.nil? && !build.empty?
30 | increment_build_number(build_number: build.to_i)
31 | end
32 |
33 | run_id = ENV["GITHUB_RUN_ID"]
34 | if !run_id.nil? && !run_id.empty?
35 | set_info_plist_value(path: "./Bark/Info.plist", key: "GitHub Run Id", value: run_id)
36 | end
37 |
38 | match(type: "appstore", readonly: is_ci)
39 |
40 | build_app(workspace: "Bark.xcworkspace", scheme: "Bark")
41 |
42 | app_store_connect_api_key(
43 | key_id: "DX95H785DP",
44 | issuer_id: ENV["APP_STORE_CONNECT_ISSUER_ID"],
45 | key_content: ENV["APP_STORE_CONNECT_KEY_CONTENT"],
46 | duration: 1200, # optional (maximum 1200)
47 | in_house: false # optional but may be required if using match/sigh
48 | )
49 |
50 | upload_to_testflight
51 |
52 | bark_key = ENV["BARK_KEY"]
53 | %x( 'curl' 'https://api.day.app/#{bark_key}/Bark%20#{version}%20(#{build})%20has%20completed%20processing?group=Github%20Actions&url=https%3A%2F%2Fgithub.com%2FFinb%2FBark%2Factions%2Fruns%2F#{run_id}' )
54 |
55 | end
56 |
57 | lane :tests do
58 | run_tests(scheme: "Bark.xcworkspace", scheme: "Bark")
59 | end
60 | end
61 |
--------------------------------------------------------------------------------
/fastlane/Matchfile:
--------------------------------------------------------------------------------
1 | git_url("https://github.com/Finb/match.git")
2 |
3 | storage_mode("git")
4 |
5 | type("appstore") # The default type, can be: appstore, adhoc, enterprise or development
6 |
7 | app_identifier(["me.fin.bark", "me.fin.bark.NotificationContent", "me.fin.bark.NotificationServiceExtension", "me.fin.bark.Intent"])
8 | # username("user@fastlane.tools") # Your Apple Developer Portal username
9 |
10 | # For all available options run `fastlane match --help`
11 | # Remove the # in the beginning of the line to enable the other options
12 |
13 | # The docs are available on https://docs.fastlane.tools/actions/match
14 |
--------------------------------------------------------------------------------
/notificationContentExtension/Base.lproj/MainInterface.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/notificationContentExtension/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | NotificationContentExtension
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSExtension
24 |
25 | NSExtensionAttributes
26 |
27 | UNNotificationExtensionCategory
28 |
29 | copy
30 | myNotificationCategory
31 |
32 | UNNotificationExtensionInitialContentSizeRatio
33 | 0.01
34 |
35 | NSExtensionMainStoryboard
36 | MainInterface
37 | NSExtensionPointIdentifier
38 | com.apple.usernotifications.content-extension
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/notificationContentExtension/NotificationContentExtension.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.application-groups
6 |
7 | group.bark
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------