2.3.0 - Unified logging and app intents #6
@@ -16,8 +16,8 @@ android {
|
|||||||
applicationId = "com.atridad.ascently"
|
applicationId = "com.atridad.ascently"
|
||||||
minSdk = 31
|
minSdk = 31
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 46
|
versionCode = 4
|
||||||
versionName = "2.2.1"
|
versionName = "2.3.0"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,10 @@ android {
|
|||||||
|
|
||||||
java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } }
|
java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } }
|
||||||
|
|
||||||
buildFeatures { compose = true }
|
buildFeatures {
|
||||||
|
compose = true
|
||||||
|
buildConfig = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_17) } }
|
kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_17) } }
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ package com.atridad.ascently.utils
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.atridad.ascently.BuildConfig
|
import com.atridad.ascently.BuildConfig
|
||||||
|
|
||||||
/**
|
|
||||||
* Centralized logging utility to ensure all mobile logging happens only in debug builds.
|
|
||||||
*/
|
|
||||||
object AppLogger {
|
object AppLogger {
|
||||||
|
|
||||||
|
private const val DEFAULT_TAG = "Ascently"
|
||||||
|
|
||||||
enum class Level(val androidLevel: Int) {
|
enum class Level(val androidLevel: Int) {
|
||||||
DEBUG(Log.DEBUG),
|
DEBUG(Log.DEBUG),
|
||||||
INFO(Log.INFO),
|
INFO(Log.INFO),
|
||||||
@@ -46,6 +45,4 @@ object AppLogger {
|
|||||||
Log.println(level.androidLevel, tag, message)
|
Log.println(level.androidLevel, tag, message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val DEFAULT_TAG = "Ascently"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/node": "^9.5.1",
|
"@astrojs/node": "^9.5.1",
|
||||||
"@astrojs/starlight": "^0.36.2",
|
"@astrojs/starlight": "^0.36.2",
|
||||||
"astro": "^5.15.9",
|
"astro": "^5.16.0",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
"sharp": "^0.34.5"
|
"sharp": "^0.34.5"
|
||||||
},
|
},
|
||||||
|
|||||||
179
docs/pnpm-lock.yaml
generated
179
docs/pnpm-lock.yaml
generated
@@ -10,13 +10,13 @@ importers:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/node':
|
'@astrojs/node':
|
||||||
specifier: ^9.5.1
|
specifier: ^9.5.1
|
||||||
version: 9.5.1(astro@5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))
|
version: 9.5.1(astro@5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))
|
||||||
'@astrojs/starlight':
|
'@astrojs/starlight':
|
||||||
specifier: ^0.36.2
|
specifier: ^0.36.2
|
||||||
version: 0.36.2(astro@5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))
|
version: 0.36.2(astro@5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))
|
||||||
astro:
|
astro:
|
||||||
specifier: ^5.15.9
|
specifier: ^5.16.0
|
||||||
version: 5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)
|
version: 5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)
|
||||||
qrcode:
|
qrcode:
|
||||||
specifier: ^1.5.4
|
specifier: ^1.5.4
|
||||||
version: 1.5.4
|
version: 1.5.4
|
||||||
@@ -39,8 +39,8 @@ packages:
|
|||||||
'@astrojs/markdown-remark@6.3.9':
|
'@astrojs/markdown-remark@6.3.9':
|
||||||
resolution: {integrity: sha512-hX2cLC/KW74Io1zIbn92kI482j9J7LleBLGCVU9EP3BeH5MVrnFawOnqD0t/q6D1Z+ZNeQG2gNKMslCcO36wng==}
|
resolution: {integrity: sha512-hX2cLC/KW74Io1zIbn92kI482j9J7LleBLGCVU9EP3BeH5MVrnFawOnqD0t/q6D1Z+ZNeQG2gNKMslCcO36wng==}
|
||||||
|
|
||||||
'@astrojs/mdx@4.3.11':
|
'@astrojs/mdx@4.3.12':
|
||||||
resolution: {integrity: sha512-ca18jxAiYDbPE1eAsNoiGnZoMYZGtfQpCmAJMXCB1WpyzTOHH7+KP1+gnKK8SFEA6XjHvjwI5Xzu8695c0Gabw==}
|
resolution: {integrity: sha512-pL3CVPtuQrPnDhWjy7zqbOibNyPaxP4VpQS8T8spwKqKzauJ4yoKyNkVTD8jrP7EAJHmBhZ7PTmUGZqOpKKp8g==}
|
||||||
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
|
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
astro: ^5.0.0
|
astro: ^5.0.0
|
||||||
@@ -694,8 +694,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0
|
astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0
|
||||||
|
|
||||||
astro@5.15.9:
|
astro@5.16.0:
|
||||||
resolution: {integrity: sha512-XLDXxu0282cC/oYHswWZm3johGlRvk9rLRS7pWVWSne+HsZe9JgrpHI+vewAJSSNHBGd1aCyaQOElT5RNGe7IQ==}
|
resolution: {integrity: sha512-GaDRs2Mngpw3dr2vc085GnORh98NiXxwIjg/EoQQQl/icZt3Z7s0BRsYHDZ8swkZbOA6wZsqWJdrNirl+iKcDg==}
|
||||||
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'}
|
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@@ -791,6 +791,10 @@ packages:
|
|||||||
comma-separated-tokens@2.0.3:
|
comma-separated-tokens@2.0.3:
|
||||||
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
|
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
|
||||||
|
|
||||||
|
commander@11.1.0:
|
||||||
|
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
|
||||||
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
common-ancestor-path@1.0.1:
|
common-ancestor-path@1.0.1:
|
||||||
resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==}
|
resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==}
|
||||||
|
|
||||||
@@ -804,18 +808,33 @@ packages:
|
|||||||
crossws@0.3.5:
|
crossws@0.3.5:
|
||||||
resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==}
|
resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==}
|
||||||
|
|
||||||
|
css-select@5.2.2:
|
||||||
|
resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==}
|
||||||
|
|
||||||
css-selector-parser@3.2.0:
|
css-selector-parser@3.2.0:
|
||||||
resolution: {integrity: sha512-L1bdkNKUP5WYxiW5dW6vA2hd3sL8BdRNLy2FCX0rLVise4eNw9nBdeBuJHxlELieSE2H1f6bYQFfwVUwWCV9rQ==}
|
resolution: {integrity: sha512-L1bdkNKUP5WYxiW5dW6vA2hd3sL8BdRNLy2FCX0rLVise4eNw9nBdeBuJHxlELieSE2H1f6bYQFfwVUwWCV9rQ==}
|
||||||
|
|
||||||
|
css-tree@2.2.1:
|
||||||
|
resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==}
|
||||||
|
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
|
||||||
|
|
||||||
css-tree@3.1.0:
|
css-tree@3.1.0:
|
||||||
resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==}
|
resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==}
|
||||||
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
|
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
|
||||||
|
|
||||||
|
css-what@6.2.2:
|
||||||
|
resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
cssesc@3.0.0:
|
cssesc@3.0.0:
|
||||||
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
csso@5.0.5:
|
||||||
|
resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
|
||||||
|
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
|
||||||
|
|
||||||
debug@4.4.3:
|
debug@4.4.3:
|
||||||
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
@@ -877,6 +896,19 @@ packages:
|
|||||||
dlv@1.1.3:
|
dlv@1.1.3:
|
||||||
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
|
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
|
||||||
|
|
||||||
|
dom-serializer@2.0.0:
|
||||||
|
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
|
||||||
|
|
||||||
|
domelementtype@2.3.0:
|
||||||
|
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
|
||||||
|
|
||||||
|
domhandler@5.0.3:
|
||||||
|
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
|
||||||
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
|
domutils@3.2.2:
|
||||||
|
resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
|
||||||
|
|
||||||
dset@3.1.4:
|
dset@3.1.4:
|
||||||
resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
|
resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -894,6 +926,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
|
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
entities@4.5.0:
|
||||||
|
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||||
|
engines: {node: '>=0.12'}
|
||||||
|
|
||||||
entities@6.0.1:
|
entities@6.0.1:
|
||||||
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
|
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
|
||||||
engines: {node: '>=0.12'}
|
engines: {node: '>=0.12'}
|
||||||
@@ -1077,8 +1113,8 @@ packages:
|
|||||||
http-cache-semantics@4.2.0:
|
http-cache-semantics@4.2.0:
|
||||||
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
|
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
|
||||||
|
|
||||||
http-errors@2.0.0:
|
http-errors@2.0.1:
|
||||||
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
|
resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
i18next@23.16.8:
|
i18next@23.16.8:
|
||||||
@@ -1219,6 +1255,9 @@ packages:
|
|||||||
mdast-util-to-string@4.0.0:
|
mdast-util-to-string@4.0.0:
|
||||||
resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
|
resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
|
||||||
|
|
||||||
|
mdn-data@2.0.28:
|
||||||
|
resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
|
||||||
|
|
||||||
mdn-data@2.12.2:
|
mdn-data@2.12.2:
|
||||||
resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==}
|
resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==}
|
||||||
|
|
||||||
@@ -1334,9 +1373,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
|
resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
mime-types@3.0.1:
|
mime-types@3.0.2:
|
||||||
resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
|
resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
mrmime@2.0.1:
|
mrmime@2.0.1:
|
||||||
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
||||||
@@ -1433,6 +1472,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
piccolore@0.1.3:
|
||||||
|
resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==}
|
||||||
|
|
||||||
picocolors@1.1.1:
|
picocolors@1.1.1:
|
||||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||||
|
|
||||||
@@ -1636,10 +1678,6 @@ packages:
|
|||||||
space-separated-tokens@2.0.2:
|
space-separated-tokens@2.0.2:
|
||||||
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
|
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
|
||||||
|
|
||||||
statuses@2.0.1:
|
|
||||||
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
|
||||||
engines: {node: '>= 0.8'}
|
|
||||||
|
|
||||||
statuses@2.0.2:
|
statuses@2.0.2:
|
||||||
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@@ -1672,6 +1710,11 @@ packages:
|
|||||||
style-to-object@1.0.14:
|
style-to-object@1.0.14:
|
||||||
resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
|
resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
|
||||||
|
|
||||||
|
svgo@4.0.0:
|
||||||
|
resolution: {integrity: sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==}
|
||||||
|
engines: {node: '>=16'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
tiny-inflate@1.0.3:
|
tiny-inflate@1.0.3:
|
||||||
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
|
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
|
||||||
|
|
||||||
@@ -1769,8 +1812,8 @@ packages:
|
|||||||
unist-util-visit@5.0.0:
|
unist-util-visit@5.0.0:
|
||||||
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
|
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
|
||||||
|
|
||||||
unstorage@1.17.2:
|
unstorage@1.17.3:
|
||||||
resolution: {integrity: sha512-cKEsD6iBWJgOMJ6vW1ID/SYuqNf8oN4yqRk8OYqaVQ3nnkJXOT1PSpaMh2QfzLs78UN5kSNRD2c/mgjT8tX7+w==}
|
resolution: {integrity: sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@azure/app-configuration': ^1.8.0
|
'@azure/app-configuration': ^1.8.0
|
||||||
'@azure/cosmos': ^4.2.0
|
'@azure/cosmos': ^4.2.0
|
||||||
@@ -1992,16 +2035,16 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@astrojs/mdx@4.3.11(astro@5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))':
|
'@astrojs/mdx@4.3.12(astro@5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/markdown-remark': 6.3.9
|
'@astrojs/markdown-remark': 6.3.9
|
||||||
'@mdx-js/mdx': 3.1.1
|
'@mdx-js/mdx': 3.1.1
|
||||||
acorn: 8.15.0
|
acorn: 8.15.0
|
||||||
astro: 5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)
|
astro: 5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)
|
||||||
es-module-lexer: 1.7.0
|
es-module-lexer: 1.7.0
|
||||||
estree-util-visit: 2.0.0
|
estree-util-visit: 2.0.0
|
||||||
hast-util-to-html: 9.0.5
|
hast-util-to-html: 9.0.5
|
||||||
picocolors: 1.1.1
|
piccolore: 0.1.3
|
||||||
rehype-raw: 7.0.0
|
rehype-raw: 7.0.0
|
||||||
remark-gfm: 4.0.1
|
remark-gfm: 4.0.1
|
||||||
remark-smartypants: 3.0.2
|
remark-smartypants: 3.0.2
|
||||||
@@ -2011,10 +2054,10 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@astrojs/node@9.5.1(astro@5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))':
|
'@astrojs/node@9.5.1(astro@5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/internal-helpers': 0.7.5
|
'@astrojs/internal-helpers': 0.7.5
|
||||||
astro: 5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)
|
astro: 5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)
|
||||||
send: 1.2.0
|
send: 1.2.0
|
||||||
server-destroy: 1.0.1
|
server-destroy: 1.0.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -2030,17 +2073,17 @@ snapshots:
|
|||||||
stream-replace-string: 2.0.0
|
stream-replace-string: 2.0.0
|
||||||
zod: 3.25.76
|
zod: 3.25.76
|
||||||
|
|
||||||
'@astrojs/starlight@0.36.2(astro@5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))':
|
'@astrojs/starlight@0.36.2(astro@5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/markdown-remark': 6.3.9
|
'@astrojs/markdown-remark': 6.3.9
|
||||||
'@astrojs/mdx': 4.3.11(astro@5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))
|
'@astrojs/mdx': 4.3.12(astro@5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))
|
||||||
'@astrojs/sitemap': 3.6.0
|
'@astrojs/sitemap': 3.6.0
|
||||||
'@pagefind/default-ui': 1.4.0
|
'@pagefind/default-ui': 1.4.0
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
'@types/js-yaml': 4.0.9
|
'@types/js-yaml': 4.0.9
|
||||||
'@types/mdast': 4.0.4
|
'@types/mdast': 4.0.4
|
||||||
astro: 5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)
|
astro: 5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)
|
||||||
astro-expressive-code: 0.41.3(astro@5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))
|
astro-expressive-code: 0.41.3(astro@5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3))
|
||||||
bcp-47: 2.1.0
|
bcp-47: 2.1.0
|
||||||
hast-util-from-html: 2.0.3
|
hast-util-from-html: 2.0.3
|
||||||
hast-util-select: 6.0.4
|
hast-util-select: 6.0.4
|
||||||
@@ -2552,12 +2595,12 @@ snapshots:
|
|||||||
|
|
||||||
astring@1.9.0: {}
|
astring@1.9.0: {}
|
||||||
|
|
||||||
astro-expressive-code@0.41.3(astro@5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)):
|
astro-expressive-code@0.41.3(astro@5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)):
|
||||||
dependencies:
|
dependencies:
|
||||||
astro: 5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)
|
astro: 5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3)
|
||||||
rehype-expressive-code: 0.41.3
|
rehype-expressive-code: 0.41.3
|
||||||
|
|
||||||
astro@5.15.9(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3):
|
astro@5.16.0(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/compiler': 2.13.0
|
'@astrojs/compiler': 2.13.0
|
||||||
'@astrojs/internal-helpers': 0.7.5
|
'@astrojs/internal-helpers': 0.7.5
|
||||||
@@ -2598,20 +2641,21 @@ snapshots:
|
|||||||
p-limit: 6.2.0
|
p-limit: 6.2.0
|
||||||
p-queue: 8.1.1
|
p-queue: 8.1.1
|
||||||
package-manager-detector: 1.5.0
|
package-manager-detector: 1.5.0
|
||||||
picocolors: 1.1.1
|
piccolore: 0.1.3
|
||||||
picomatch: 4.0.3
|
picomatch: 4.0.3
|
||||||
prompts: 2.4.2
|
prompts: 2.4.2
|
||||||
rehype: 13.0.2
|
rehype: 13.0.2
|
||||||
semver: 7.7.3
|
semver: 7.7.3
|
||||||
shiki: 3.15.0
|
shiki: 3.15.0
|
||||||
smol-toml: 1.5.2
|
smol-toml: 1.5.2
|
||||||
|
svgo: 4.0.0
|
||||||
tinyexec: 1.0.2
|
tinyexec: 1.0.2
|
||||||
tinyglobby: 0.2.15
|
tinyglobby: 0.2.15
|
||||||
tsconfck: 3.1.6(typescript@5.9.3)
|
tsconfck: 3.1.6(typescript@5.9.3)
|
||||||
ultrahtml: 1.6.0
|
ultrahtml: 1.6.0
|
||||||
unifont: 0.6.0
|
unifont: 0.6.0
|
||||||
unist-util-visit: 5.0.0
|
unist-util-visit: 5.0.0
|
||||||
unstorage: 1.17.2
|
unstorage: 1.17.3
|
||||||
vfile: 6.0.3
|
vfile: 6.0.3
|
||||||
vite: 6.4.1(@types/node@24.10.1)
|
vite: 6.4.1(@types/node@24.10.1)
|
||||||
vitefu: 1.1.1(vite@6.4.1(@types/node@24.10.1))
|
vitefu: 1.1.1(vite@6.4.1(@types/node@24.10.1))
|
||||||
@@ -2735,6 +2779,8 @@ snapshots:
|
|||||||
|
|
||||||
comma-separated-tokens@2.0.3: {}
|
comma-separated-tokens@2.0.3: {}
|
||||||
|
|
||||||
|
commander@11.1.0: {}
|
||||||
|
|
||||||
common-ancestor-path@1.0.1: {}
|
common-ancestor-path@1.0.1: {}
|
||||||
|
|
||||||
cookie-es@1.2.2: {}
|
cookie-es@1.2.2: {}
|
||||||
@@ -2745,15 +2791,34 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
uncrypto: 0.1.3
|
uncrypto: 0.1.3
|
||||||
|
|
||||||
|
css-select@5.2.2:
|
||||||
|
dependencies:
|
||||||
|
boolbase: 1.0.0
|
||||||
|
css-what: 6.2.2
|
||||||
|
domhandler: 5.0.3
|
||||||
|
domutils: 3.2.2
|
||||||
|
nth-check: 2.1.1
|
||||||
|
|
||||||
css-selector-parser@3.2.0: {}
|
css-selector-parser@3.2.0: {}
|
||||||
|
|
||||||
|
css-tree@2.2.1:
|
||||||
|
dependencies:
|
||||||
|
mdn-data: 2.0.28
|
||||||
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
css-tree@3.1.0:
|
css-tree@3.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
mdn-data: 2.12.2
|
mdn-data: 2.12.2
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
|
css-what@6.2.2: {}
|
||||||
|
|
||||||
cssesc@3.0.0: {}
|
cssesc@3.0.0: {}
|
||||||
|
|
||||||
|
csso@5.0.5:
|
||||||
|
dependencies:
|
||||||
|
css-tree: 2.2.1
|
||||||
|
|
||||||
debug@4.4.3:
|
debug@4.4.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
@@ -2794,6 +2859,24 @@ snapshots:
|
|||||||
|
|
||||||
dlv@1.1.3: {}
|
dlv@1.1.3: {}
|
||||||
|
|
||||||
|
dom-serializer@2.0.0:
|
||||||
|
dependencies:
|
||||||
|
domelementtype: 2.3.0
|
||||||
|
domhandler: 5.0.3
|
||||||
|
entities: 4.5.0
|
||||||
|
|
||||||
|
domelementtype@2.3.0: {}
|
||||||
|
|
||||||
|
domhandler@5.0.3:
|
||||||
|
dependencies:
|
||||||
|
domelementtype: 2.3.0
|
||||||
|
|
||||||
|
domutils@3.2.2:
|
||||||
|
dependencies:
|
||||||
|
dom-serializer: 2.0.0
|
||||||
|
domelementtype: 2.3.0
|
||||||
|
domhandler: 5.0.3
|
||||||
|
|
||||||
dset@3.1.4: {}
|
dset@3.1.4: {}
|
||||||
|
|
||||||
ee-first@1.1.1: {}
|
ee-first@1.1.1: {}
|
||||||
@@ -2804,6 +2887,8 @@ snapshots:
|
|||||||
|
|
||||||
encodeurl@2.0.0: {}
|
encodeurl@2.0.0: {}
|
||||||
|
|
||||||
|
entities@4.5.0: {}
|
||||||
|
|
||||||
entities@6.0.1: {}
|
entities@6.0.1: {}
|
||||||
|
|
||||||
es-module-lexer@1.7.0: {}
|
es-module-lexer@1.7.0: {}
|
||||||
@@ -3153,12 +3238,12 @@ snapshots:
|
|||||||
|
|
||||||
http-cache-semantics@4.2.0: {}
|
http-cache-semantics@4.2.0: {}
|
||||||
|
|
||||||
http-errors@2.0.0:
|
http-errors@2.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
depd: 2.0.0
|
depd: 2.0.0
|
||||||
inherits: 2.0.4
|
inherits: 2.0.4
|
||||||
setprototypeof: 1.2.0
|
setprototypeof: 1.2.0
|
||||||
statuses: 2.0.1
|
statuses: 2.0.2
|
||||||
toidentifier: 1.0.1
|
toidentifier: 1.0.1
|
||||||
|
|
||||||
i18next@23.16.8:
|
i18next@23.16.8:
|
||||||
@@ -3411,6 +3496,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/mdast': 4.0.4
|
'@types/mdast': 4.0.4
|
||||||
|
|
||||||
|
mdn-data@2.0.28: {}
|
||||||
|
|
||||||
mdn-data@2.12.2: {}
|
mdn-data@2.12.2: {}
|
||||||
|
|
||||||
micromark-core-commonmark@2.0.3:
|
micromark-core-commonmark@2.0.3:
|
||||||
@@ -3689,7 +3776,7 @@ snapshots:
|
|||||||
|
|
||||||
mime-db@1.54.0: {}
|
mime-db@1.54.0: {}
|
||||||
|
|
||||||
mime-types@3.0.1:
|
mime-types@3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-db: 1.54.0
|
mime-db: 1.54.0
|
||||||
|
|
||||||
@@ -3794,6 +3881,8 @@ snapshots:
|
|||||||
|
|
||||||
path-exists@4.0.0: {}
|
path-exists@4.0.0: {}
|
||||||
|
|
||||||
|
piccolore@0.1.3: {}
|
||||||
|
|
||||||
picocolors@1.1.1: {}
|
picocolors@1.1.1: {}
|
||||||
|
|
||||||
picomatch@2.3.1: {}
|
picomatch@2.3.1: {}
|
||||||
@@ -4049,8 +4138,8 @@ snapshots:
|
|||||||
escape-html: 1.0.3
|
escape-html: 1.0.3
|
||||||
etag: 1.8.1
|
etag: 1.8.1
|
||||||
fresh: 2.0.0
|
fresh: 2.0.0
|
||||||
http-errors: 2.0.0
|
http-errors: 2.0.1
|
||||||
mime-types: 3.0.1
|
mime-types: 3.0.2
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
on-finished: 2.4.1
|
on-finished: 2.4.1
|
||||||
range-parser: 1.2.1
|
range-parser: 1.2.1
|
||||||
@@ -4123,8 +4212,6 @@ snapshots:
|
|||||||
|
|
||||||
space-separated-tokens@2.0.2: {}
|
space-separated-tokens@2.0.2: {}
|
||||||
|
|
||||||
statuses@2.0.1: {}
|
|
||||||
|
|
||||||
statuses@2.0.2: {}
|
statuses@2.0.2: {}
|
||||||
|
|
||||||
stream-replace-string@2.0.0: {}
|
stream-replace-string@2.0.0: {}
|
||||||
@@ -4162,6 +4249,16 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
inline-style-parser: 0.2.7
|
inline-style-parser: 0.2.7
|
||||||
|
|
||||||
|
svgo@4.0.0:
|
||||||
|
dependencies:
|
||||||
|
commander: 11.1.0
|
||||||
|
css-select: 5.2.2
|
||||||
|
css-tree: 3.1.0
|
||||||
|
css-what: 6.2.2
|
||||||
|
csso: 5.0.5
|
||||||
|
picocolors: 1.1.1
|
||||||
|
sax: 1.4.3
|
||||||
|
|
||||||
tiny-inflate@1.0.3: {}
|
tiny-inflate@1.0.3: {}
|
||||||
|
|
||||||
tinyexec@1.0.2: {}
|
tinyexec@1.0.2: {}
|
||||||
@@ -4267,7 +4364,7 @@ snapshots:
|
|||||||
unist-util-is: 6.0.1
|
unist-util-is: 6.0.1
|
||||||
unist-util-visit-parents: 6.0.2
|
unist-util-visit-parents: 6.0.2
|
||||||
|
|
||||||
unstorage@1.17.2:
|
unstorage@1.17.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
anymatch: 3.1.3
|
anymatch: 3.1.3
|
||||||
chokidar: 4.0.3
|
chokidar: 4.0.3
|
||||||
|
|||||||
@@ -465,7 +465,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Ascently/Ascently.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Ascently/Ascently.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 31;
|
CURRENT_PROJECT_VERSION = 32;
|
||||||
DEVELOPMENT_TEAM = 4BC9Y2LL4B;
|
DEVELOPMENT_TEAM = 4BC9Y2LL4B;
|
||||||
DRIVERKIT_DEPLOYMENT_TARGET = 24.6;
|
DRIVERKIT_DEPLOYMENT_TARGET = 24.6;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@@ -487,7 +487,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
||||||
MARKETING_VERSION = 2.2.1;
|
MARKETING_VERSION = 2.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.atridad.Ascently;
|
PRODUCT_BUNDLE_IDENTIFIER = com.atridad.Ascently;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@@ -513,7 +513,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Ascently/Ascently.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Ascently/Ascently.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 31;
|
CURRENT_PROJECT_VERSION = 32;
|
||||||
DEVELOPMENT_TEAM = 4BC9Y2LL4B;
|
DEVELOPMENT_TEAM = 4BC9Y2LL4B;
|
||||||
DRIVERKIT_DEPLOYMENT_TARGET = 24.6;
|
DRIVERKIT_DEPLOYMENT_TARGET = 24.6;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@@ -535,7 +535,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
||||||
MARKETING_VERSION = 2.2.1;
|
MARKETING_VERSION = 2.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.atridad.Ascently;
|
PRODUCT_BUNDLE_IDENTIFIER = com.atridad.Ascently;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@@ -602,7 +602,7 @@
|
|||||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
CODE_SIGN_ENTITLEMENTS = SessionStatusLiveExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = SessionStatusLiveExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 31;
|
CURRENT_PROJECT_VERSION = 32;
|
||||||
DEVELOPMENT_TEAM = 4BC9Y2LL4B;
|
DEVELOPMENT_TEAM = 4BC9Y2LL4B;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = SessionStatusLive/Info.plist;
|
INFOPLIST_FILE = SessionStatusLive/Info.plist;
|
||||||
@@ -613,7 +613,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 2.2.1;
|
MARKETING_VERSION = 2.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.atridad.Ascently.SessionStatusLive;
|
PRODUCT_BUNDLE_IDENTIFIER = com.atridad.Ascently.SessionStatusLive;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -632,7 +632,7 @@
|
|||||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
CODE_SIGN_ENTITLEMENTS = SessionStatusLiveExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = SessionStatusLiveExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 31;
|
CURRENT_PROJECT_VERSION = 32;
|
||||||
DEVELOPMENT_TEAM = 4BC9Y2LL4B;
|
DEVELOPMENT_TEAM = 4BC9Y2LL4B;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = SessionStatusLive/Info.plist;
|
INFOPLIST_FILE = SessionStatusLive/Info.plist;
|
||||||
@@ -643,7 +643,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 2.2.1;
|
MARKETING_VERSION = 2.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.atridad.Ascently.SessionStatusLive;
|
PRODUCT_BUNDLE_IDENTIFIER = com.atridad.Ascently.SessionStatusLive;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
|||||||
Binary file not shown.
33
ios/Ascently/AppIntents/AscentlyShortcuts.swift
Normal file
33
ios/Ascently/AppIntents/AscentlyShortcuts.swift
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import AppIntents
|
||||||
|
|
||||||
|
/// Provides a curated list of the most useful Ascently shortcuts for Siri and the Shortcuts app.
|
||||||
|
/// Surfaces intents that users can trigger hands-free to manage their climbing sessions.
|
||||||
|
struct AscentlyShortcuts: AppShortcutsProvider {
|
||||||
|
|
||||||
|
static var shortcutTileColor: ShortcutTileColor {
|
||||||
|
.teal
|
||||||
|
}
|
||||||
|
|
||||||
|
static var appShortcuts: [AppShortcut] {
|
||||||
|
return [
|
||||||
|
AppShortcut(
|
||||||
|
intent: StartLastGymSessionIntent(),
|
||||||
|
phrases: [
|
||||||
|
"Start my climb in \(.applicationName)",
|
||||||
|
"Begin my last gym session in \(.applicationName)",
|
||||||
|
],
|
||||||
|
shortTitle: "Start Climb",
|
||||||
|
systemImageName: "figure.climbing"
|
||||||
|
),
|
||||||
|
AppShortcut(
|
||||||
|
intent: EndActiveSessionIntent(),
|
||||||
|
phrases: [
|
||||||
|
"Finish my climb in \(.applicationName)",
|
||||||
|
"End my session in \(.applicationName)",
|
||||||
|
],
|
||||||
|
shortTitle: "End Climb",
|
||||||
|
systemImageName: "flag.checkered"
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
40
ios/Ascently/AppIntents/EndActiveSessionIntent.swift
Normal file
40
ios/Ascently/AppIntents/EndActiveSessionIntent.swift
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import AppIntents
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/// Ends the currently active climbing session so logging stays in sync across devices.
|
||||||
|
/// Exposed to Shortcuts so users can wrap up a session without opening the app.
|
||||||
|
struct EndActiveSessionIntent: AppIntent {
|
||||||
|
|
||||||
|
static var title: LocalizedStringResource {
|
||||||
|
"End Active Session"
|
||||||
|
}
|
||||||
|
|
||||||
|
static var description: IntentDescription {
|
||||||
|
IntentDescription(
|
||||||
|
"Stop the active climbing session and save its progress in Ascently."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
static var openAppWhenRun: Bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
func perform() async throws -> some IntentResult & ProvidesDialog {
|
||||||
|
do {
|
||||||
|
let summary = try await SessionIntentController().endActiveSession()
|
||||||
|
let dialog = IntentDialog("Session at \(summary.gymName) ended. Nice work!")
|
||||||
|
return .result(dialog: dialog)
|
||||||
|
} catch SessionIntentError.noActiveSession {
|
||||||
|
// No active session is fine - just return a friendly message
|
||||||
|
let dialog = IntentDialog("No active session to end.")
|
||||||
|
return .result(dialog: dialog)
|
||||||
|
} catch {
|
||||||
|
// Re-throw other errors
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var parameterSummary: some ParameterSummary {
|
||||||
|
Summary("End my current climbing session")
|
||||||
|
}
|
||||||
|
}
|
||||||
95
ios/Ascently/AppIntents/SessionIntentSupport.swift
Normal file
95
ios/Ascently/AppIntents/SessionIntentSupport.swift
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
/// User-visible errors that can arise while handling session-related intents.
|
||||||
|
enum SessionIntentError: LocalizedError {
|
||||||
|
case noRecentGym
|
||||||
|
case noActiveSession
|
||||||
|
case failedToStartSession
|
||||||
|
case failedToEndSession
|
||||||
|
|
||||||
|
var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .noRecentGym:
|
||||||
|
return "There's no recent gym to start a session with."
|
||||||
|
case .noActiveSession:
|
||||||
|
return "There isn't an active session to end right now."
|
||||||
|
case .failedToStartSession:
|
||||||
|
return "Ascently couldn't start a new session."
|
||||||
|
case .failedToEndSession:
|
||||||
|
return "Ascently couldn't finish the active session."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SessionIntentSummary: Sendable {
|
||||||
|
let sessionId: UUID
|
||||||
|
let gymName: String
|
||||||
|
let status: SessionStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Central controller that exposes the minimal climbing session operations used by App Intents and shortcuts.
|
||||||
|
@MainActor
|
||||||
|
final class SessionIntentController {
|
||||||
|
|
||||||
|
private let dataManager: ClimbingDataManager
|
||||||
|
|
||||||
|
init(dataManager: ClimbingDataManager = .shared) {
|
||||||
|
self.dataManager = dataManager
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Starts a new session using the most recently visited gym.
|
||||||
|
func startSessionWithLastUsedGym() async throws -> SessionIntentSummary {
|
||||||
|
// Give a moment for data to be ready if app just launched
|
||||||
|
if dataManager.gyms.isEmpty {
|
||||||
|
try? await Task.sleep(nanoseconds: 500_000_000) // 0.5 seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let lastGym = dataManager.getLastUsedGym() else {
|
||||||
|
logFailure(.noRecentGym, context: "No recorded sessions available")
|
||||||
|
throw SessionIntentError.noRecentGym
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let startedSession = await dataManager.startSessionAsync(gymId: lastGym.id) else {
|
||||||
|
logFailure(.failedToStartSession, context: "Data manager failed to create new session")
|
||||||
|
throw SessionIntentError.failedToStartSession
|
||||||
|
}
|
||||||
|
|
||||||
|
return SessionIntentSummary(
|
||||||
|
sessionId: startedSession.id,
|
||||||
|
gymName: lastGym.name,
|
||||||
|
status: startedSession.status
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ends the currently active climbing session, if one exists.
|
||||||
|
func endActiveSession() async throws -> SessionIntentSummary {
|
||||||
|
guard let activeSession = dataManager.activeSession else {
|
||||||
|
logFailure(.noActiveSession, context: "No active session stored in data manager")
|
||||||
|
throw SessionIntentError.noActiveSession
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let completedSession = await dataManager.endSessionAsync(activeSession.id) else {
|
||||||
|
logFailure(
|
||||||
|
.failedToEndSession, context: "Data manager failed to complete active session")
|
||||||
|
throw SessionIntentError.failedToEndSession
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let gym = dataManager.gym(withId: completedSession.gymId) else {
|
||||||
|
logFailure(
|
||||||
|
.failedToEndSession,
|
||||||
|
context: "Gym missing for completed session \(completedSession.id)")
|
||||||
|
throw SessionIntentError.failedToEndSession
|
||||||
|
}
|
||||||
|
|
||||||
|
return SessionIntentSummary(
|
||||||
|
sessionId: completedSession.id,
|
||||||
|
gymName: gym.name,
|
||||||
|
status: completedSession.status
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func logFailure(_ error: SessionIntentError, context: String) {
|
||||||
|
// Logging from intent context - errors are visible to user via dialog
|
||||||
|
print("SessionIntentError: \(error). Context: \(context)")
|
||||||
|
}
|
||||||
|
}
|
||||||
43
ios/Ascently/AppIntents/StartLastGymSessionIntent.swift
Normal file
43
ios/Ascently/AppIntents/StartLastGymSessionIntent.swift
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import AppIntents
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/// Starts a climbing session at the most recently visited gym.
|
||||||
|
/// Exposed to Shortcuts so users can begin logging without opening the app.
|
||||||
|
struct StartLastGymSessionIntent: AppIntent {
|
||||||
|
|
||||||
|
static var title: LocalizedStringResource {
|
||||||
|
"Start Last Gym Session"
|
||||||
|
}
|
||||||
|
|
||||||
|
static var description: IntentDescription {
|
||||||
|
IntentDescription(
|
||||||
|
"Begin a new climbing session using the most recent gym you visited in Ascently."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
static var openAppWhenRun: Bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
func perform() async throws -> some IntentResult & ProvidesDialog {
|
||||||
|
// Delay to ensure app has time to fully initialize if just launched
|
||||||
|
try? await Task.sleep(nanoseconds: 1_000_000_000) // 1 second
|
||||||
|
|
||||||
|
let summary = try await SessionIntentController().startSessionWithLastUsedGym()
|
||||||
|
|
||||||
|
// Give Live Activity extra time to start
|
||||||
|
try? await Task.sleep(nanoseconds: 500_000_000) // 0.5 seconds
|
||||||
|
|
||||||
|
return .result(
|
||||||
|
dialog: Self.successDialog(for: summary.gymName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func successDialog(for gymName: String) -> IntentDialog {
|
||||||
|
IntentDialog("Session started at \(gymName). Have an awesome climb!")
|
||||||
|
}
|
||||||
|
|
||||||
|
static var parameterSummary: some ParameterSummary {
|
||||||
|
Summary("Start a session at my last gym")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,19 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
class AppDelegate: NSObject, UIApplicationDelegate {
|
||||||
|
func application(
|
||||||
|
_ application: UIApplication,
|
||||||
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
||||||
|
) -> Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct AscentlyApp: App {
|
struct AscentlyApp: App {
|
||||||
|
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||||||
|
@Environment(\.scenePhase) private var scenePhase
|
||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
ContentView()
|
ContentView()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@StateObject private var dataManager = ClimbingDataManager()
|
@StateObject private var dataManager = ClimbingDataManager.shared
|
||||||
@State private var selectedTab = 0
|
@State private var selectedTab = 0
|
||||||
@Environment(\.scenePhase) private var scenePhase
|
@Environment(\.scenePhase) private var scenePhase
|
||||||
@State private var notificationObservers: [NSObjectProtocol] = []
|
@State private var notificationObservers: [NSObjectProtocol] = []
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>NSSupportsLiveActivities</key>
|
<key>NSSupportsLiveActivities</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
<string>This app needs access to your photo library to add photos to climbing problems.</string>
|
<string>This app needs access to your photo library to add photos to climbing problems.</string>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import UniformTypeIdentifiers
|
|||||||
@MainActor
|
@MainActor
|
||||||
class ClimbingDataManager: ObservableObject {
|
class ClimbingDataManager: ObservableObject {
|
||||||
|
|
||||||
|
static let shared = ClimbingDataManager()
|
||||||
|
|
||||||
@Published var gyms: [Gym] = []
|
@Published var gyms: [Gym] = []
|
||||||
@Published var problems: [Problem] = []
|
@Published var problems: [Problem] = []
|
||||||
@Published var sessions: [ClimbSession] = []
|
@Published var sessions: [ClimbSession] = []
|
||||||
@@ -78,7 +80,7 @@ class ClimbingDataManager: ObservableObject {
|
|||||||
let name: String
|
let name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
fileprivate init() {
|
||||||
_ = ImageManager.shared
|
_ = ImageManager.shared
|
||||||
migrateFromOpenClimbIfNeeded()
|
migrateFromOpenClimbIfNeeded()
|
||||||
loadAllData()
|
loadAllData()
|
||||||
@@ -415,9 +417,16 @@ class ClimbingDataManager: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func startSession(gymId: UUID, notes: String? = nil) {
|
func startSession(gymId: UUID, notes: String? = nil) {
|
||||||
// End any currently active session
|
Task { @MainActor in
|
||||||
|
await startSessionAsync(gymId: gymId, notes: notes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
func startSessionAsync(gymId: UUID, notes: String? = nil) async -> ClimbSession? {
|
||||||
|
// End any currently active session before starting a new one
|
||||||
if let currentActive = activeSession {
|
if let currentActive = activeSession {
|
||||||
endSession(currentActive.id)
|
await endSessionAsync(currentActive.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
let newSession = ClimbSession(gymId: gymId, notes: notes)
|
let newSession = ClimbSession(gymId: gymId, notes: notes)
|
||||||
@@ -430,64 +439,70 @@ class ClimbingDataManager: ObservableObject {
|
|||||||
|
|
||||||
// MARK: - Start Live Activity for new session
|
// MARK: - Start Live Activity for new session
|
||||||
if let gym = gym(withId: gymId) {
|
if let gym = gym(withId: gymId) {
|
||||||
Task {
|
await LiveActivityManager.shared.startLiveActivity(
|
||||||
await LiveActivityManager.shared.startLiveActivity(
|
for: newSession,
|
||||||
for: newSession, gymName: gym.name)
|
gymName: gym.name)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if healthKitService.isEnabled {
|
if healthKitService.isEnabled {
|
||||||
Task {
|
do {
|
||||||
do {
|
try await healthKitService.startWorkout(
|
||||||
try await healthKitService.startWorkout(
|
startDate: newSession.startTime ?? Date(),
|
||||||
startDate: newSession.startTime ?? Date(),
|
sessionId: newSession.id)
|
||||||
sessionId: newSession.id)
|
} catch {
|
||||||
} catch {
|
AppLogger.error(
|
||||||
AppLogger.error(
|
"Failed to start HealthKit workout: \(error.localizedDescription)",
|
||||||
"Failed to start HealthKit workout: \(error.localizedDescription)",
|
tag: LogTag.climbingData)
|
||||||
tag: LogTag.climbingData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return newSession
|
||||||
}
|
}
|
||||||
|
|
||||||
func endSession(_ sessionId: UUID) {
|
func endSession(_ sessionId: UUID) {
|
||||||
if let session = sessions.first(where: { $0.id == sessionId && $0.status == .active }),
|
Task { @MainActor in
|
||||||
|
await endSessionAsync(sessionId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
func endSessionAsync(_ sessionId: UUID) async -> ClimbSession? {
|
||||||
|
guard
|
||||||
|
let session = sessions.first(where: { $0.id == sessionId && $0.status == .active }),
|
||||||
let index = sessions.firstIndex(where: { $0.id == sessionId })
|
let index = sessions.firstIndex(where: { $0.id == sessionId })
|
||||||
{
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
let completedSession = session.completed()
|
let completedSession = session.completed()
|
||||||
sessions[index] = completedSession
|
sessions[index] = completedSession
|
||||||
|
|
||||||
if activeSession?.id == sessionId {
|
if activeSession?.id == sessionId {
|
||||||
activeSession = nil
|
activeSession = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
saveActiveSession()
|
saveActiveSession()
|
||||||
saveSessions()
|
saveSessions()
|
||||||
DataStateManager.shared.updateDataState()
|
DataStateManager.shared.updateDataState()
|
||||||
|
|
||||||
// Trigger auto-sync if enabled
|
// Trigger auto-sync if enabled
|
||||||
syncService.triggerAutoSync(dataManager: self)
|
syncService.triggerAutoSync(dataManager: self)
|
||||||
|
|
||||||
// MARK: - End Live Activity after session ends
|
// MARK: - End Live Activity after session ends
|
||||||
Task {
|
await LiveActivityManager.shared.endLiveActivity()
|
||||||
await LiveActivityManager.shared.endLiveActivity()
|
|
||||||
}
|
|
||||||
|
|
||||||
if healthKitService.isEnabled {
|
if healthKitService.isEnabled {
|
||||||
Task {
|
do {
|
||||||
do {
|
try await healthKitService.endWorkout(
|
||||||
try await healthKitService.endWorkout(
|
endDate: completedSession.endTime ?? Date())
|
||||||
endDate: completedSession.endTime ?? Date())
|
} catch {
|
||||||
} catch {
|
AppLogger.error(
|
||||||
AppLogger.error(
|
"Failed to end HealthKit workout: \(error.localizedDescription)",
|
||||||
"Failed to end HealthKit workout: \(error.localizedDescription)",
|
tag: LogTag.climbingData)
|
||||||
tag: LogTag.climbingData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return completedSession
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSession(_ session: ClimbSession) {
|
func updateSession(_ session: ClimbSession) {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import WidgetKit
|
|||||||
struct SessionStatusLiveBundle: WidgetBundle {
|
struct SessionStatusLiveBundle: WidgetBundle {
|
||||||
var body: some Widget {
|
var body: some Widget {
|
||||||
SessionStatusLive()
|
SessionStatusLive()
|
||||||
SessionStatusLiveControl()
|
|
||||||
SessionStatusLiveLiveActivity()
|
SessionStatusLiveLiveActivity()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
//
|
|
||||||
// SessionStatusLiveControl.swift
|
|
||||||
|
|
||||||
import AppIntents
|
|
||||||
import SwiftUI
|
|
||||||
import WidgetKit
|
|
||||||
|
|
||||||
struct SessionStatusLiveControl: ControlWidget {
|
|
||||||
static let kind: String = "com.atridad.Ascently.SessionStatusLive"
|
|
||||||
|
|
||||||
var body: some ControlWidgetConfiguration {
|
|
||||||
AppIntentControlConfiguration(
|
|
||||||
kind: Self.kind,
|
|
||||||
provider: Provider()
|
|
||||||
) { value in
|
|
||||||
ControlWidgetToggle(
|
|
||||||
"Start Timer",
|
|
||||||
isOn: value.isRunning,
|
|
||||||
action: StartTimerIntent(value.name)
|
|
||||||
) { isRunning in
|
|
||||||
Label(isRunning ? "On" : "Off", systemImage: "timer")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.displayName("Timer")
|
|
||||||
.description("A an example control that runs a timer.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension SessionStatusLiveControl {
|
|
||||||
struct Value {
|
|
||||||
var isRunning: Bool
|
|
||||||
var name: String
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Provider: AppIntentControlValueProvider {
|
|
||||||
func previewValue(configuration: TimerConfiguration) -> Value {
|
|
||||||
SessionStatusLiveControl.Value(isRunning: false, name: configuration.timerName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func currentValue(configuration: TimerConfiguration) async throws -> Value {
|
|
||||||
let isRunning = true // Check if the timer is running
|
|
||||||
return SessionStatusLiveControl.Value(
|
|
||||||
isRunning: isRunning, name: configuration.timerName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TimerConfiguration: ControlConfigurationIntent {
|
|
||||||
static let title: LocalizedStringResource = "Timer Name Configuration"
|
|
||||||
|
|
||||||
@Parameter(title: "Timer Name", default: "Timer")
|
|
||||||
var timerName: String
|
|
||||||
}
|
|
||||||
|
|
||||||
struct StartTimerIntent: SetValueIntent {
|
|
||||||
static let title: LocalizedStringResource = "Start a timer"
|
|
||||||
|
|
||||||
@Parameter(title: "Timer Name")
|
|
||||||
var name: String
|
|
||||||
|
|
||||||
@Parameter(title: "Timer is running")
|
|
||||||
var value: Bool
|
|
||||||
|
|
||||||
init() {}
|
|
||||||
|
|
||||||
init(_ name: String) {
|
|
||||||
self.name = name
|
|
||||||
}
|
|
||||||
|
|
||||||
func perform() async throws -> some IntentResult {
|
|
||||||
// Start the timer…
|
|
||||||
return .result()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "2.2.0"
|
const VERSION = "2.3.0"
|
||||||
|
|
||||||
func min(a, b int) int {
|
func min(a, b int) int {
|
||||||
if a < b {
|
if a < b {
|
||||||
|
|||||||
Reference in New Issue
Block a user