[PM-10562] Added the complication to the watchOS app (#836)
10
.github/workflows/build.yml
vendored
@ -156,6 +156,7 @@ jobs:
|
||||
"dist_share_extension.mobileprovision"
|
||||
"dist_bitwarden_watch_app.mobileprovision"
|
||||
"dist_bitwarden_watch_app_extension.mobileprovision"
|
||||
"dist_bitwarden_watch_widget_extension.mobileprovision"
|
||||
)
|
||||
|
||||
for FILE in "${profiles[@]}"
|
||||
@ -178,6 +179,7 @@ jobs:
|
||||
"dist_beta_share_extension.mobileprovision"
|
||||
"dist_beta_bitwarden_watch_app.mobileprovision"
|
||||
"dist_beta_bitwarden_watch_app_extension.mobileprovision"
|
||||
"dist_beta_bitwarden_watch_widget_extension.mobileprovision"
|
||||
)
|
||||
|
||||
for FILE in "${profiles[@]}"
|
||||
@ -274,6 +276,7 @@ jobs:
|
||||
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_share_extension.mobileprovision
|
||||
WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_bitwarden_watch_app.mobileprovision
|
||||
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_bitwarden_watch_app_extension.mobileprovision
|
||||
WATCH_WIDGET_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_bitwarden_watch_widget_extension.mobileprovision
|
||||
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles
|
||||
|
||||
mkdir -p "$PROFILES_DIR_PATH"
|
||||
@ -296,6 +299,9 @@ jobs:
|
||||
WATCH_APP_EXTENSION_UUID=$(grep UUID -A1 -a $WATCH_APP_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||
cp $WATCH_APP_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_APP_EXTENSION_UUID.mobileprovision"
|
||||
|
||||
WATCH_WIDGET_EXTENSION_UUID=$(grep UUID -A1 -a $WATCH_WIDGET_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||
cp $WATCH_WIDGET_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_WIDGET_EXTENSION_UUID.mobileprovision"
|
||||
|
||||
- name: Configure beta provisioning profiles
|
||||
if: env.BUILD_VARIANT == 'Beta'
|
||||
run: |
|
||||
@ -305,6 +311,7 @@ jobs:
|
||||
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_beta_share_extension.mobileprovision
|
||||
WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_beta_bitwarden_watch_app.mobileprovision
|
||||
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_beta_bitwarden_watch_app_extension.mobileprovision
|
||||
WATCH_WIDGET_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_beta_bitwarden_watch_widget_extension.mobileprovision
|
||||
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles
|
||||
|
||||
mkdir -p "$PROFILES_DIR_PATH"
|
||||
@ -327,6 +334,9 @@ jobs:
|
||||
WATCH_APP_EXTENSION_UUID=$(grep UUID -A1 -a $WATCH_APP_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||
cp $WATCH_APP_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_APP_EXTENSION_UUID.mobileprovision"
|
||||
|
||||
WATCH_WIDGET_EXTENSION_UUID=$(grep UUID -A1 -a $WATCH_WIDGET_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||
cp $WATCH_WIDGET_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_WIDGET_EXTENSION_UUID.mobileprovision"
|
||||
|
||||
- name: Update beta export compliance key
|
||||
if: env.BUILD_VARIANT == 'Beta'
|
||||
run: |
|
||||
|
||||
@ -626,11 +626,14 @@ class AutofillCredentialServiceTests: BitwardenTestCase { // swiftlint:disable:t
|
||||
}
|
||||
|
||||
/// `syncIdentities(vaultLockStatus:)` doesn't remove identities if the store's state is disabled.
|
||||
func test_syncIdentities_removeDisabled() {
|
||||
func test_syncIdentities_removeDisabled() async throws {
|
||||
try await waitAndResetRemoveAllCredentialIdentitiesCalled()
|
||||
identityStore.state.mockIsEnabled = false
|
||||
|
||||
vaultTimeoutService.vaultLockStatusSubject.send(nil)
|
||||
waitFor(identityStore.stateCalled)
|
||||
try await waitForAsync {
|
||||
self.identityStore.stateCalled
|
||||
}
|
||||
|
||||
XCTAssertFalse(identityStore.removeAllCredentialIdentitiesCalled)
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 969 B |
|
Before Width: | Height: | Size: 1.1 KiB |
@ -1,27 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Circular38mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : "<=145"
|
||||
},
|
||||
{
|
||||
"filename" : "Circular44mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
{
|
||||
"assets" : [
|
||||
{
|
||||
"filename" : "Circular.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "circular"
|
||||
},
|
||||
{
|
||||
"filename" : "Extra Large.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "extra-large"
|
||||
},
|
||||
{
|
||||
"filename" : "Graphic Bezel.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "graphic-bezel"
|
||||
},
|
||||
{
|
||||
"filename" : "Graphic Circular.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "graphic-circular"
|
||||
},
|
||||
{
|
||||
"filename" : "Graphic Corner.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "graphic-corner"
|
||||
},
|
||||
{
|
||||
"filename" : "Graphic Extra Large.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "graphic-extra-large"
|
||||
},
|
||||
{
|
||||
"filename" : "Graphic Large Rectangular.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "graphic-large-rectangular"
|
||||
},
|
||||
{
|
||||
"filename" : "Modular.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "modular"
|
||||
},
|
||||
{
|
||||
"filename" : "Utilitarian.imageset",
|
||||
"idiom" : "watch",
|
||||
"role" : "utilitarian"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ExtraLarge38mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : "<=145"
|
||||
},
|
||||
{
|
||||
"filename" : "ExtraLarge44mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "GraphicBezel44mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.2 KiB |
@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "GraphicCircular44mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.2 KiB |
@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "GraphicCorner44mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,27 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "GraphicExtraLarge38mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : "<=145"
|
||||
},
|
||||
{
|
||||
"filename" : "GraphicExtraLarge44mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
@ -1,20 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "GraphicModular38mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : "<=145"
|
||||
},
|
||||
{
|
||||
"filename" : "GraphicModular44mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
@ -1,27 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "GraphicUtilitarian38mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : "<=145"
|
||||
},
|
||||
{
|
||||
"filename" : "GraphicUtilitarian44mm2x.png",
|
||||
"idiom" : "watch",
|
||||
"scale" : "2x",
|
||||
"screen-width" : ">183"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"auto-scaling" : "auto"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
12
BitwardenWatchApp/Assets.xcassets/ComplicationIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "bw-logo.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
BitwardenWatchApp/Assets.xcassets/ComplicationIcon.imageset/bw-logo.pdf
vendored
Normal file
@ -6,64 +6,94 @@ class ComplicationController: NSObject, CLKComplicationDataSource {
|
||||
func getComplicationDescriptors(handler: @escaping ([CLKComplicationDescriptor]) -> Void) {
|
||||
let descriptors = [
|
||||
CLKComplicationDescriptor(
|
||||
identifier: "complication",
|
||||
identifier: "bitwarden-watch-complication",
|
||||
displayName: "Bitwarden",
|
||||
supportedFamilies: CLKComplicationFamily.allCases
|
||||
supportedFamilies: [
|
||||
CLKComplicationFamily.circularSmall,
|
||||
CLKComplicationFamily.graphicCircular,
|
||||
CLKComplicationFamily.graphicCorner,
|
||||
CLKComplicationFamily.utilitarianSmall,
|
||||
]
|
||||
),
|
||||
// Multiple complication support can be added here with more descriptors
|
||||
]
|
||||
|
||||
// Call the handler with the currently supported complication descriptors
|
||||
handler(descriptors)
|
||||
}
|
||||
|
||||
func handleSharedComplicationDescriptors(_: [CLKComplicationDescriptor]) {
|
||||
// Do any necessary work to support these newly shared complication descriptors
|
||||
}
|
||||
|
||||
// MARK: - Timeline Configuration
|
||||
|
||||
func getTimelineEndDate(for _: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
|
||||
// Call the handler with the last entry date you can currently provide or nil if you can't support future
|
||||
// timelines
|
||||
handler(nil)
|
||||
}
|
||||
|
||||
func getPrivacyBehavior(
|
||||
for _: CLKComplication,
|
||||
withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void
|
||||
) {
|
||||
// Call the handler with your desired behavior when the device is locked
|
||||
handler(.showOnLockScreen)
|
||||
}
|
||||
|
||||
// MARK: - Timeline Population
|
||||
|
||||
func getCurrentTimelineEntry(
|
||||
for _: CLKComplication,
|
||||
for complication: CLKComplication,
|
||||
withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void
|
||||
) {
|
||||
// Call the handler with the current timeline entry
|
||||
handler(nil)
|
||||
}
|
||||
guard let icon = UIImage(named: "ComplicationIcon") else {
|
||||
handler(nil)
|
||||
return
|
||||
}
|
||||
let imageProvider = CLKFullColorImageProvider(fullColorImage: icon)
|
||||
|
||||
func getTimelineEntries(
|
||||
for _: CLKComplication,
|
||||
after _: Date,
|
||||
limit _: Int,
|
||||
withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void
|
||||
) {
|
||||
// Call the handler with the timeline entries after the given date
|
||||
handler(nil)
|
||||
switch complication.family {
|
||||
case .circularSmall:
|
||||
let template = CLKComplicationTemplateCircularSmallSimpleImage(
|
||||
imageProvider: CLKImageProvider(onePieceImage: icon)
|
||||
)
|
||||
handler(CLKComplicationTimelineEntry(date: .now, complicationTemplate: template))
|
||||
case .graphicCircular:
|
||||
let template = CLKComplicationTemplateGraphicCircularImage(imageProvider: imageProvider)
|
||||
handler(CLKComplicationTimelineEntry(date: .now, complicationTemplate: template))
|
||||
case .graphicCorner:
|
||||
let template = CLKComplicationTemplateGraphicCornerCircularImage(imageProvider: imageProvider)
|
||||
handler(CLKComplicationTimelineEntry(date: .now, complicationTemplate: template))
|
||||
case .utilitarianSmall:
|
||||
let template = CLKComplicationTemplateUtilitarianSmallSquare(
|
||||
imageProvider: CLKImageProvider(onePieceImage: icon)
|
||||
)
|
||||
handler(CLKComplicationTimelineEntry(date: .now, complicationTemplate: template))
|
||||
default:
|
||||
handler(nil)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Sample Templates
|
||||
|
||||
func getLocalizableSampleTemplate(
|
||||
for _: CLKComplication,
|
||||
for complication: CLKComplication,
|
||||
withHandler handler: @escaping (CLKComplicationTemplate?) -> Void
|
||||
) {
|
||||
// This method will be called once per supported complication, and the results will be cached
|
||||
handler(nil)
|
||||
guard let icon = UIImage(named: "ComplicationIcon") else {
|
||||
handler(nil)
|
||||
return
|
||||
}
|
||||
let imageProvider = CLKFullColorImageProvider(fullColorImage: icon)
|
||||
|
||||
switch complication.family {
|
||||
case .circularSmall:
|
||||
let template = CLKComplicationTemplateCircularSmallSimpleImage(
|
||||
imageProvider: CLKImageProvider(onePieceImage: icon)
|
||||
)
|
||||
handler(template)
|
||||
case .graphicCircular:
|
||||
let template = CLKComplicationTemplateGraphicCircularImage(imageProvider: imageProvider)
|
||||
handler(template)
|
||||
case .graphicCorner:
|
||||
let template = CLKComplicationTemplateGraphicCornerCircularImage(imageProvider: imageProvider)
|
||||
handler(template)
|
||||
case .utilitarianSmall:
|
||||
let template = CLKComplicationTemplateUtilitarianSmallSquare(
|
||||
imageProvider: CLKImageProvider(onePieceImage: icon)
|
||||
)
|
||||
handler(template)
|
||||
default:
|
||||
handler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>CLKComplicationPrincipalClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).ComplicationController</string>
|
||||
<key>WKApplication</key>
|
||||
<true/>
|
||||
<key>WKCompanionAppBundleIdentifier</key>
|
||||
|
||||
29
BitwardenWatchWidgetExtension/Application/Support/Info.plist
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Bitwarden Watch Widget</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Bitwarden Watch Widget Extension</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.widgetkit-extension</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
12
BitwardenWatchWidgetExtension/Assets.xcassets/AccentedComplicationIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "bw-logo.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
BitwardenWatchWidgetExtension/Assets.xcassets/AccentedComplicationIcon.imageset/bw-logo.pdf
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Icon-1024.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 30 KiB |
12
BitwardenWatchWidgetExtension/Assets.xcassets/ComplicationIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Icon-100.png",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
BitwardenWatchWidgetExtension/Assets.xcassets/ComplicationIcon.imageset/Icon-100.png
vendored
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
import SwiftUI
|
||||
import WidgetKit
|
||||
|
||||
/// Provider that provides the entries for the widget.
|
||||
struct Provider: TimelineProvider {
|
||||
func placeholder(in context: Context) -> SimpleEntry {
|
||||
SimpleEntry(date: Date())
|
||||
}
|
||||
|
||||
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) {
|
||||
let entry = SimpleEntry(date: Date())
|
||||
completion(entry)
|
||||
}
|
||||
|
||||
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
|
||||
let entry = SimpleEntry(date: Date())
|
||||
let timeline = Timeline(entries: [entry], policy: .never)
|
||||
completion(timeline)
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple timeline entry to comply with the widget provider.
|
||||
struct SimpleEntry: TimelineEntry {
|
||||
let date: Date
|
||||
}
|
||||
|
||||
/// Entry view to be used to render the widget.
|
||||
struct BitwardenComplicationEntryView: View {
|
||||
/// The widget family.
|
||||
@Environment(\.widgetFamily) var family
|
||||
/// The widget rendering mode.
|
||||
@Environment(\.widgetRenderingMode) var renderingMode
|
||||
|
||||
/// The provider entry
|
||||
var entry: Provider.Entry
|
||||
|
||||
var body: some View {
|
||||
if renderingMode == .fullColor {
|
||||
Image("ComplicationIcon")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.clipShape(Circle())
|
||||
.padding()
|
||||
} else {
|
||||
Image("AccentedComplicationIcon")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.padding(5)
|
||||
.widgetAccentable()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension entry point of the widget.
|
||||
@main
|
||||
struct BitwardenWatchWidgetExtension: Widget {
|
||||
let kind: String = "BitwardenWatchWidgetExtension"
|
||||
|
||||
var body: some WidgetConfiguration {
|
||||
StaticConfiguration(kind: kind, provider: Provider()) { entry in
|
||||
if #available(watchOS 10.0, *) {
|
||||
BitwardenComplicationEntryView(entry: entry)
|
||||
.containerBackground(.fill.tertiary, for: .widget)
|
||||
} else {
|
||||
BitwardenComplicationEntryView(entry: entry)
|
||||
.padding()
|
||||
.background()
|
||||
}
|
||||
}
|
||||
.configurationDisplayName("Bitwarden")
|
||||
.supportedFamilies([.accessoryCircular, .accessoryCorner, .accessoryInline])
|
||||
}
|
||||
}
|
||||
|
||||
@available(watchOS 10.0, *)
|
||||
#Preview(as: .accessoryCorner) {
|
||||
BitwardenWatchWidgetExtension()
|
||||
} timeline: {
|
||||
SimpleEntry(date: .now)
|
||||
}
|
||||
BIN
BitwardenWatchWidgetExtension/Icon-50.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
@ -1,7 +1,8 @@
|
||||
#include "./Common.xcconfig"
|
||||
#include "./WatchCommon.xcconfig"
|
||||
#include? "./Local.xcconfig"
|
||||
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-Dev
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_ID).watchkitapp
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(BASE_WATCH_BUNDLE_ID)
|
||||
WK_COMPANION_APP_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_ID)
|
||||
PROVISIONING_PROFILE_SPECIFIER = $(PROVISIONING_PROFILE_SPECIFIER_WATCH_APP)
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
#include "./Common.xcconfig"
|
||||
#include "./WatchCommon.xcconfig"
|
||||
#include? "./Local.xcconfig"
|
||||
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = $(APPICON_NAME)
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_ID).watchkitapp
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(BASE_WATCH_BUNDLE_ID)
|
||||
WK_COMPANION_APP_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_ID)
|
||||
PROVISIONING_PROFILE_SPECIFIER = $(PROVISIONING_PROFILE_SPECIFIER_WATCH_APP)
|
||||
|
||||
6
Configs/BitwardenWatchWidgetExtension.xcconfig
Normal file
@ -0,0 +1,6 @@
|
||||
#include "./Common.xcconfig"
|
||||
#include "./WatchCommon.xcconfig"
|
||||
#include? "./Local.xcconfig"
|
||||
|
||||
PRODUCT_BUNDLE_IDENTIFIER = $(BASE_WATCH_BUNDLE_ID).widget-extension
|
||||
PROVISIONING_PROFILE_SPECIFIER = $(PROVISIONING_PROFILE_SPECIFIER_WATCH_WIDGET_EXTENSION)
|
||||
@ -18,6 +18,7 @@ APPICON_NAME = AppIcon
|
||||
// PROVISIONING_PROFILE_SPECIFIER_AUTOFILL_EXTENSION = <Optional provisioning profile specifier for the autofill extension>
|
||||
// PROVISIONING_PROFILE_SPECIFIER_SHARE_EXTENSION = <Optional provisioning profile specifier for the share extension>
|
||||
// PROVISIONING_PROFILE_SPECIFIER_WATCH_APP = <Optional provisioning profile specifier for the watch app>
|
||||
// PROVISIONING_PROFILE_SPECIFIER_WATCH_WIDGET_EXTENSION = <Optional provisioning profile specifier for the watch widget extension>
|
||||
//
|
||||
// This should allow Xcode to build the application based on these settings without
|
||||
// code signing errors or having to modify the project itself.
|
||||
|
||||
4
Configs/WatchCommon.xcconfig
Normal file
@ -0,0 +1,4 @@
|
||||
#include "./Common.xcconfig"
|
||||
#include? "./Local.xcconfig"
|
||||
|
||||
BASE_WATCH_BUNDLE_ID = $(BASE_BUNDLE_ID).watchkitapp
|
||||
@ -49,6 +49,7 @@ PROVISIONING_PROFILE_SPECIFIER_ACTION_EXTENSION = ${profile_prefix} Extension
|
||||
PROVISIONING_PROFILE_SPECIFIER_AUTOFILL_EXTENSION = ${profile_prefix} Autofill
|
||||
PROVISIONING_PROFILE_SPECIFIER_SHARE_EXTENSION = ${profile_prefix} Share Extension
|
||||
PROVISIONING_PROFILE_SPECIFIER_WATCH_APP = ${profile_prefix} Bitwarden Watch App
|
||||
PROVISIONING_PROFILE_SPECIFIER_WATCH_WIDGET_EXTENSION = ${profile_prefix} Bitwarden Watch Widget Extension
|
||||
EOF
|
||||
|
||||
cat << EOF > ${export_options_file}
|
||||
@ -70,6 +71,8 @@ cat << EOF > ${export_options_file}
|
||||
<string>${profile_prefix} Share Extension</string>
|
||||
<key>${ios_bundle_id}.watchkitapp</key>
|
||||
<string>${profile_prefix} Bitwarden Watch App</string>
|
||||
<key>${ios_bundle_id}.watchkitapp.widget-extension</key>
|
||||
<string>${profile_prefix} Bitwarden Watch Widget Extension</string>
|
||||
</dict>
|
||||
<key>manageAppVersionAndBuildNumber</key>
|
||||
<false/>
|
||||
|
||||
18
project.yml
@ -117,6 +117,10 @@ schemes:
|
||||
build:
|
||||
targets:
|
||||
BitwardenWatchApp: all
|
||||
BitwardenWatchWidgetExtension:
|
||||
build:
|
||||
targets:
|
||||
BitwardenWatchWidgetExtension: all
|
||||
targets:
|
||||
Bitwarden:
|
||||
type: application
|
||||
@ -396,6 +400,7 @@ targets:
|
||||
- path: BitwardenWatchApp/GoogleService-Info.plist
|
||||
buildPhase: resources
|
||||
dependencies:
|
||||
- target: BitwardenWatchWidgetExtension
|
||||
- package: Firebase
|
||||
product: FirebaseCrashlytics
|
||||
postBuildScripts:
|
||||
@ -405,3 +410,16 @@ targets:
|
||||
inputFiles:
|
||||
- ${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}
|
||||
- ${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}
|
||||
|
||||
BitwardenWatchWidgetExtension:
|
||||
type: app-extension
|
||||
platform: watchOS
|
||||
deploymentTarget: 9.0
|
||||
configFiles:
|
||||
Debug: Configs/BitwardenWatchWidgetExtension.xcconfig
|
||||
Release: Configs/BitwardenWatchWidgetExtension.xcconfig
|
||||
settings:
|
||||
base:
|
||||
INFOPLIST_FILE: BitwardenWatchWidgetExtension/Application/Support/Info.plist
|
||||
sources:
|
||||
- path: BitwardenWatchWidgetExtension
|
||||
|
||||