Compare commits

..

1 Commits

Author SHA1 Message Date
AppCakes 6bbc0632f9 build: f2992d4b-fbd4-4c34-aa8c-d652ae24e63d 2026-05-28 19:26:10 +00:00
65 changed files with 186 additions and 891 deletions
Binary file not shown.
+1 -1
View File
@@ -4,7 +4,7 @@ android {
namespace = "io.ionic.starter" namespace = "io.ionic.starter"
compileSdk = rootProject.ext.compileSdkVersion compileSdk = rootProject.ext.compileSdkVersion
defaultConfig { defaultConfig {
applicationId "io.demoapp.app" applicationId "io.ionic.starter"
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1 versionCode 1
-6
View File
@@ -21,12 +21,6 @@
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="io.demoapp.app" />
</intent-filter>
</activity> </activity>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 771 B

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 16 KiB

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="splashBackground">#FFFFFF</color>
</resources>
+2 -2
View File
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<resources> <resources>
<string name="app_name">DemoApp</string> <string name="app_name">PowerSlap</string>
<string name="title_activity_main">DemoApp</string> <string name="title_activity_main">PowerSlap</string>
<string name="package_name">io.ionic.starter</string> <string name="package_name">io.ionic.starter</string>
<string name="custom_url_scheme">io.ionic.starter</string> <string name="custom_url_scheme">io.ionic.starter</string>
</resources> </resources>
+1 -3
View File
@@ -17,8 +17,6 @@
<style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen"> <style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/splashBackground</item> <item name="android:background">@drawable/splash</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_logo</item>
<item name="postSplashScreenTheme">@style/AppTheme.NoActionBar</item>
</style> </style>
</resources> </resources>
+1
View File
@@ -15,4 +15,5 @@ ext {
cordovaAndroidVersion = '14.0.1' cordovaAndroidVersion = '14.0.1'
rgcfaIncludeGoogle = true rgcfaIncludeGoogle = true
androidxCredentialsVersion = '1.3.0' androidxCredentialsVersion = '1.3.0'
javaVersion = JavaVersion.VERSION_17
} }
+2 -2
View File
@@ -1,8 +1,8 @@
import type { CapacitorConfig } from '@capacitor/cli'; import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = { const config: CapacitorConfig = {
appId: 'io.demoapp.app', appId: 'io.powerslap.app',
appName: 'DemoApp', appName: 'PowerSlap',
webDir: 'dist', webDir: 'dist',
plugins: { plugins: {
FirebaseAuthentication: { FirebaseAuthentication: {
+27 -44
View File
@@ -11,9 +11,6 @@ workflows:
- $HOME/.gradle/caches - $HOME/.gradle/caches
- $HOME/.gradle/wrapper - $HOME/.gradle/wrapper
scripts: scripts:
# Template ships with optional native plugins (maps, push, firebase auth) that most apps
# won't use. Keeping unused plugins in package.json adds SPM/Gradle deps and bloats the
# build. Strip any that have no import in src/ so only actually-used plugins are compiled.
- name: Strip unused scaffold packages - name: Strip unused scaffold packages
script: | script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
@@ -24,16 +21,10 @@ workflows:
echo "Keeping $pkg (used in src/)" echo "Keeping $pkg (used in src/)"
fi fi
done done
# Delete package-lock.json (generated if user ever ran npm locally) so it doesn't
# conflict with yarn.lock. --legacy-peer-deps silences peer dep warnings from older
# Ionic/React packages that haven't updated their peerDependencies for React 18/19.
- name: Install dependencies - name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets - name: Build web assets
script: npm run build script: npm run build
# Firebase config files are injected as base64 env vars by the Appcakes backend at
# build time. Decode them here so cap sync and Gradle can pick them up. Optional —
# builds without Firebase still succeed; native Firebase SDK just won't initialise.
- name: Write Firebase config - name: Write Firebase config
script: | script: |
if [ -n "$GOOGLE_SERVICES_JSON" ]; then if [ -n "$GOOGLE_SERVICES_JSON" ]; then
@@ -46,8 +37,6 @@ workflows:
echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist
echo "Wrote GoogleService-Info.plist ($(wc -c < ios/App/App/GoogleService-Info.plist) bytes)" echo "Wrote GoogleService-Info.plist ($(wc -c < ios/App/App/GoogleService-Info.plist) bytes)"
fi fi
# cap sync copies the built web assets (dist/) into android/app/src/main/assets/public/
# and updates Capacitor plugin registrations in MainActivity. Must run after npm build.
- name: Capacitor sync - name: Capacitor sync
script: npx cap sync android script: npx cap sync android
- name: Set up debug keystore - name: Set up debug keystore
@@ -239,25 +228,26 @@ workflows:
script: rm -f package-lock.json && npm install --legacy-peer-deps script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets - name: Build web assets
script: npm run build script: npm run build
# First sync: regenerates CapApp-SPM/Package.swift with the correct plugin list.
# Note: this project uses Capacitor SPM (no CocoaPods/Podfile), so cap sync replaces
# pod install — it regenerates CapApp-SPM/Package.swift and copies web assets.
- name: Capacitor sync - name: Capacitor sync
script: npx cap sync ios script: npx cap sync ios
# Decode Firebase plist to disk so it is present during the second sync.
- name: Write Firebase config - name: Write Firebase config
script: | script: |
if [ -n "$GOOGLE_SERVICE_INFO_PLIST" ]; then if [ -n "$GOOGLE_SERVICE_INFO_PLIST" ]; then
echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist
ruby -e "
require 'xcodeproj'
project = Xcodeproj::Project.open('ios/App/App.xcodeproj')
target = project.targets.find { |t| t.name == 'App' }
app_group = project.main_group['App']
unless app_group.files.find { |f| f.path == 'GoogleService-Info.plist' }
file_ref = app_group.new_reference('GoogleService-Info.plist')
target.resources_build_phase.add_file_reference(file_ref)
project.save
end
"
fi fi
# Second sync ensures CapApp-SPM/Package.swift is consistent after the plist write.
- name: Capacitor sync - name: Capacitor sync
script: npx cap sync ios script: npx cap sync ios
# Run configure_xcode.rb after both syncs so its xcodeproj changes (plist file
# reference + SPM product linking) are not overwritten by a subsequent cap sync.
# configure_xcode.rb is stamped fresh from template on every build push.
- name: Configure Xcode project
script: ruby configure_xcode.rb
- name: Set up signing - name: Set up signing
script: | script: |
keychain initialize keychain initialize
@@ -282,23 +272,11 @@ workflows:
echo "No signing credentials configured — build will fail at signing" echo "No signing credentials configured — build will fail at signing"
exit 1 exit 1
fi fi
# --workspace: Capacitor SPM projects require workspace context for Xcode to resolve
# the CapApp-SPM local package. Using --project causes xcodebuild to fail on
# Xcode 26+ because SPM resolution requires workspace scope. App.xcworkspace is a
# static file committed to the template (not generated by cap sync) that wraps
# App.xcodeproj for this purpose.
# --no-show-build-settings: xcode-project runs xcodebuild -showBuildSettings as a
# pre-build diagnostic. Xcode 26 fails this step for SPM projects even with
# --workspace, so we skip it. The actual archive step still surfaces real errors.
# --disable-xcpretty: xcpretty reformats and filters xcodebuild output, swallowing
# the actual error lines when a build fails. Raw output makes failures debuggable.
- name: Build IPA - name: Build IPA
script: | script: |
xcode-project build-ipa \ xcode-project build-ipa \
--workspace ios/App/App.xcworkspace \ --project ios/App/App.xcodeproj \
--scheme App \ --scheme App
--no-show-build-settings \
--disable-xcpretty
artifacts: artifacts:
- build/ios/ipa/*.ipa - build/ios/ipa/*.ipa
@@ -326,15 +304,24 @@ workflows:
script: npm run build script: npm run build
- name: Capacitor sync - name: Capacitor sync
script: npx cap sync ios script: npx cap sync ios
- name: Configure Xcode project - name: Write Firebase config
script: | script: |
if [ -n "$GOOGLE_SERVICE_INFO_PLIST" ]; then if [ -n "$GOOGLE_SERVICE_INFO_PLIST" ]; then
echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist
ruby -e "
require 'xcodeproj'
project = Xcodeproj::Project.open('ios/App/App.xcodeproj')
target = project.targets.find { |t| t.name == 'App' }
app_group = project.main_group['App']
unless app_group.files.find { |f| f.path == 'GoogleService-Info.plist' }
file_ref = app_group.new_reference('GoogleService-Info.plist')
target.resources_build_phase.add_file_reference(file_ref)
project.save
end
"
fi fi
- name: Capacitor sync - name: Capacitor sync
script: npx cap sync ios script: npx cap sync ios
- name: Configure Xcode project
script: ruby configure_xcode.rb
- name: Set up signing - name: Set up signing
script: | script: |
keychain initialize keychain initialize
@@ -356,16 +343,12 @@ workflows:
echo "$CM_PROVISIONING_PROFILE" | base64 --decode > "$HOME/Library/MobileDevice/Provisioning Profiles/profile.mobileprovision" echo "$CM_PROVISIONING_PROFILE" | base64 --decode > "$HOME/Library/MobileDevice/Provisioning Profiles/profile.mobileprovision"
xcode-project use-profiles xcode-project use-profiles
fi fi
# See ios-debug Build IPA comments for --workspace, --no-show-build-settings,
# and --disable-xcpretty rationale — same reasons apply here.
- name: Build IPA - name: Build IPA
script: | script: |
xcode-project build-ipa \ xcode-project build-ipa \
--workspace ios/App/App.xcworkspace \ --project ios/App/App.xcodeproj \
--scheme App \ --scheme App \
--config Release \ --config Release
--no-show-build-settings \
--disable-xcpretty
- name: Publish - name: Publish
script: | script: |
if [ "$SUBMIT_TO_TESTFLIGHT" = "true" ] || [ "$SUBMIT_TO_APP_STORE" = "true" ]; then if [ "$SUBMIT_TO_TESTFLIGHT" = "true" ] || [ "$SUBMIT_TO_APP_STORE" = "true" ]; then
-118
View File
@@ -1,118 +0,0 @@
#!/usr/bin/env ruby
# configure_xcode.rb — stamped fresh from template on every build (see gitea.service.ts)
#
# 1. Adds GoogleService-Info.plist to the Xcode target if present (xcodeproj gem)
# 2. Scans Swift sources for Firebase imports and injects matching products into
# CapApp-SPM/Package.swift — the correct approach for Capacitor SPM projects
# where all native linking goes through CapApp-SPM, not App.xcodeproj directly.
require 'xcodeproj'
PROJECT_PATH = 'ios/App/App.xcodeproj'
TARGET_NAME = 'App'
PLIST_SRC = 'ios/App/App/GoogleService-Info.plist'
CAP_APP_SPM = 'ios/App/CapApp-SPM/Package.swift'
# ── 1. GoogleService-Info.plist ───────────────────────────────────────────────
if File.exist?(PLIST_SRC)
project = Xcodeproj::Project.open(PROJECT_PATH)
target = project.targets.find { |t| t.name == TARGET_NAME }
if target
app_group = project.main_group['App']
unless app_group&.files&.find { |f| f.path == 'GoogleService-Info.plist' }
file_ref = app_group.new_reference('GoogleService-Info.plist')
target.resources_build_phase.add_file_reference(file_ref)
project.save
puts "Added GoogleService-Info.plist to target"
end
end
end
# ── 2. Scan Swift sources for Firebase imports ────────────────────────────────
swift_files = Dir['ios/App/App/**/*.swift']
firebase_imports = swift_files
.flat_map { |f| File.readlines(f) rescue [] }
.grep(/^\s*import\s+Firebase\w+/)
.map { |l| l.strip.split(/\s+/).last }
.uniq
.sort
if firebase_imports.empty?
puts "No Firebase imports found — skipping CapApp-SPM update"
exit 0
end
puts "Firebase imports detected: #{firebase_imports.join(', ')}"
unless File.exist?(CAP_APP_SPM)
warn "WARNING: #{CAP_APP_SPM} not found — was cap sync run?"
exit 0
end
# ── 3. Detect firebase-ios-sdk URL and version from node_modules ──────────────
# Read from the ACTUAL node_modules on this build machine (populated by npm install)
# so the version we inject matches what @capacitor-firebase/* already resolved.
firebase_url = nil
firebase_version = nil
Dir['node_modules/@capacitor-firebase/**/Package.swift',
'node_modules/@capacitor/push-notifications/**/Package.swift'].each do |f|
content = File.read(f) rescue next
url_m = content.match(/\.package\(url:\s*"(https:\/\/github\.com\/firebase\/firebase-ios-sdk[^"]*)"/)
ver_m = content.match(/firebase-ios-sdk[^)]+from:\s*"(\d+)\.(\d+)\.(\d+)"/)
next unless url_m && ver_m
firebase_url = url_m[1]
major = ver_m[1].to_i
firebase_version = "#{major}.0.0"
puts "Detected firebase-ios-sdk from #{f}: url=#{firebase_url} → using from: \"#{firebase_version}\""
break
end
# Fallback — should rarely be needed
unless firebase_url
firebase_url = 'https://github.com/firebase/firebase-ios-sdk.git'
firebase_version = '11.0.0'
puts "Could not detect firebase-ios-sdk version from node_modules — using fallback #{firebase_version}"
end
firebase_pkg = 'firebase-ios-sdk'
lines = File.read(CAP_APP_SPM).split("\n")
# ── 4. Inject firebase-ios-sdk as a direct package dependency if missing ──────
# Normalise URL check to handle both with and without .git suffix
firebase_url_base = firebase_url.sub(/\.git$/, '')
unless lines.any? { |l| l.include?(firebase_url_base) }
last_pkg_idx = lines.rindex { |l| l.include?('.package(') }
if last_pkg_idx
lines[last_pkg_idx] = lines[last_pkg_idx].rstrip
lines[last_pkg_idx] += ',' unless lines[last_pkg_idx].end_with?(',')
lines.insert(last_pkg_idx + 1,
" .package(url: \"#{firebase_url}\", from: \"#{firebase_version}\")")
puts "Added #{firebase_pkg} to CapApp-SPM package dependencies"
else
warn "WARNING: no .package( line found in #{CAP_APP_SPM} — cannot inject dependency"
end
end
# ── 5. Inject each detected product into the target dependencies if missing ───
firebase_imports.each do |product|
next if product == 'Firebase' # umbrella import — not a linkable SPM product
product_str = ".product(name: \"#{product}\", package: \"#{firebase_pkg}\")"
next if lines.any? { |l| l.include?(product_str) }
last_prod_idx = lines.rindex { |l| l.include?('.product(') }
if last_prod_idx
lines[last_prod_idx] = lines[last_prod_idx].rstrip
lines[last_prod_idx] += ',' unless lines[last_prod_idx].end_with?(',')
lines.insert(last_prod_idx + 1, " #{product_str}")
puts "Added #{product} to CapApp-SPM target dependencies"
else
warn "WARNING: no .product( line found in #{CAP_APP_SPM} — cannot inject #{product}"
end
end
File.write(CAP_APP_SPM, lines.join("\n"))
puts "CapApp-SPM/Package.swift updated"
+2 -6
View File
@@ -26,7 +26,6 @@
504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
1A4EB3C21FED79650016851F /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = "<group>"; };
50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; }; 50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
958DCC722DB07C7200EA8C5F /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = debug.xcconfig; path = ../debug.xcconfig; sourceTree = SOURCE_ROOT; }; 958DCC722DB07C7200EA8C5F /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = debug.xcconfig; path = ../debug.xcconfig; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@@ -69,7 +68,6 @@
504EC30E1FED79650016851F /* Assets.xcassets */, 504EC30E1FED79650016851F /* Assets.xcassets */,
504EC3101FED79650016851F /* LaunchScreen.storyboard */, 504EC3101FED79650016851F /* LaunchScreen.storyboard */,
504EC3131FED79650016851F /* Info.plist */, 504EC3131FED79650016851F /* Info.plist */,
1A4EB3C21FED79650016851F /* App.entitlements */,
2FAD9762203C412B000D30F8 /* config.xml */, 2FAD9762203C412B000D30F8 /* config.xml */,
50B271D01FEDC1A000F3C39B /* public */, 50B271D01FEDC1A000F3C39B /* public */,
); );
@@ -297,7 +295,6 @@
baseConfigurationReference = 958DCC722DB07C7200EA8C5F /* debug.xcconfig */; baseConfigurationReference = 958DCC722DB07C7200EA8C5F /* debug.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
INFOPLIST_FILE = App/Info.plist; INFOPLIST_FILE = App/Info.plist;
@@ -308,7 +305,7 @@
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = io.demoapp.app; PRODUCT_BUNDLE_IDENTIFIER = io.powerslap.app;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@@ -320,7 +317,6 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
INFOPLIST_FILE = App/Info.plist; INFOPLIST_FILE = App/Info.plist;
@@ -330,7 +326,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = io.demoapp.app; PRODUCT_BUNDLE_IDENTIFIER = io.powerslap.app;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
-7
View File
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:App.xcodeproj">
</FileRef>
</Workspace>
@@ -1,8 +0,0 @@
<?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>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -1,122 +1,14 @@
{ {
"images" : [ "images" : [
{ {
"idiom": "iphone", "filename" : "AppIcon-512@2x.png",
"scale": "1x", "idiom" : "universal",
"size": "20x20", "platform" : "ios",
"filename": "icon-20.png" "size" : "1024x1024"
},
{
"idiom": "ipad",
"scale": "1x",
"size": "20x20",
"filename": "icon-20.png"
},
{
"idiom": "iphone",
"scale": "1x",
"size": "29x29",
"filename": "icon-29.png"
},
{
"idiom": "ipad",
"scale": "1x",
"size": "29x29",
"filename": "icon-29.png"
},
{
"idiom": "ipad",
"scale": "1x",
"size": "40x40",
"filename": "icon-40.png"
},
{
"idiom": "iphone",
"scale": "2x",
"size": "20x20",
"filename": "icon-40.png"
},
{
"idiom": "iphone",
"scale": "2x",
"size": "29x29",
"filename": "icon-58.png"
},
{
"idiom": "ipad",
"scale": "2x",
"size": "29x29",
"filename": "icon-58.png"
},
{
"idiom": "iphone",
"scale": "3x",
"size": "20x20",
"filename": "icon-60.png"
},
{
"idiom": "ipad",
"scale": "1x",
"size": "76x76",
"filename": "icon-76.png"
},
{
"idiom": "iphone",
"scale": "2x",
"size": "40x40",
"filename": "icon-80.png"
},
{
"idiom": "ipad",
"scale": "2x",
"size": "40x40",
"filename": "icon-80.png"
},
{
"idiom": "iphone",
"scale": "3x",
"size": "29x29",
"filename": "icon-87.png"
},
{
"idiom": "iphone",
"scale": "2x",
"size": "60x60",
"filename": "icon-120.png"
},
{
"idiom": "iphone",
"scale": "3x",
"size": "40x40",
"filename": "icon-120.png"
},
{
"idiom": "ipad",
"scale": "2x",
"size": "76x76",
"filename": "icon-152.png"
},
{
"idiom": "ipad",
"scale": "2x",
"size": "83.5x83.5",
"filename": "icon-167.png"
},
{
"idiom": "iphone",
"scale": "3x",
"size": "60x60",
"filename": "icon-180.png"
},
{
"idiom": "ios-marketing",
"scale": "1x",
"size": "1024x1024",
"filename": "icon-1024.png"
} }
], ],
"info" : { "info" : {
"author": "appsuite", "author" : "xcode",
"version" : 1 "version" : 1
} }
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

+13 -3
View File
@@ -2,12 +2,22 @@
"images" : [ "images" : [
{ {
"idiom" : "universal", "idiom" : "universal",
"filename": "splash.png", "filename" : "splash-2732x2732-2.png",
"scale" : "1x" "scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "splash-2732x2732-1.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "splash-2732x2732.png",
"scale" : "3x"
} }
], ],
"info" : { "info" : {
"author": "appsuite", "version" : 1,
"version": 1 "author" : "xcode"
} }
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

+3 -3
View File
@@ -7,7 +7,7 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>en</string> <string>en</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>DemoApp</string> <string>PowerSlap</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@@ -51,10 +51,10 @@
<array> <array>
<dict> <dict>
<key>CFBundleURLName</key> <key>CFBundleURLName</key>
<string>io.demoapp.app</string> <string>io.powerslap.app</string>
<key>CFBundleURLSchemes</key> <key>CFBundleURLSchemes</key>
<array> <array>
<string>io.demoapp.app</string> <string>io.powerslap.app</string>
</array> </array>
</dict> </dict>
</array> </array>
-363
View File
@@ -1,363 +0,0 @@
workflows:
android-debug:
name: Android Debug APK
max_build_duration: 45
instance_type: mac_mini_m2
environment:
node: 22
java: 21
cache:
cache_paths:
- $HOME/.gradle/caches
- $HOME/.gradle/wrapper
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICES_JSON" ]; then
echo "$GOOGLE_SERVICES_JSON" | base64 --decode > android/app/google-services.json
echo "Wrote google-services.json ($(wc -c < android/app/google-services.json) bytes)"
else
echo "GOOGLE_SERVICES_JSON is empty — skipping"
fi
if [ -n "$GOOGLE_SERVICE_INFO_PLIST" ]; then
echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist
echo "Wrote GoogleService-Info.plist ($(wc -c < ios/App/App/GoogleService-Info.plist) bytes)"
fi
- name: Capacitor sync
script: npx cap sync android
- name: Set up debug keystore
script: |
if [ -n "$CM_DEBUG_KEYSTORE" ]; then
echo "$CM_DEBUG_KEYSTORE" | base64 --decode > /tmp/debug-keystore.p12
fi
- name: Build debug APK
script: |
cd android
if [ -n "$CM_DEBUG_KEYSTORE" ]; then
./gradlew assembleDebug \
-Pandroid.injected.signing.store.file=/tmp/debug-keystore.p12 \
-Pandroid.injected.signing.store.password=$CM_DEBUG_KEYSTORE_PASSWORD \
-Pandroid.injected.signing.key.alias=debug \
-Pandroid.injected.signing.key.password=$CM_DEBUG_KEYSTORE_PASSWORD \
--no-daemon
else
./gradlew assembleDebug --no-daemon
fi
artifacts:
- android/app/build/outputs/apk/debug/app-debug.apk
android-release-apk:
name: Android Release APK
max_build_duration: 45
instance_type: mac_mini_m2
environment:
node: 22
java: 21
cache:
cache_paths:
- $HOME/.gradle/caches
- $HOME/.gradle/wrapper
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICES_JSON" ]; then
echo "$GOOGLE_SERVICES_JSON" | base64 --decode > android/app/google-services.json
fi
- name: Capacitor sync
script: npx cap sync android
- name: Set up keystore
script: echo "$CM_KEYSTORE" | base64 --decode > /tmp/keystore.jks
- name: Build Release APK
script: |
cd android
./gradlew assembleRelease \
-Pandroid.injected.signing.store.file=/tmp/keystore.jks \
-Pandroid.injected.signing.store.password=$CM_KEYSTORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$CM_KEY_ALIAS \
-Pandroid.injected.signing.key.password=$CM_KEY_PASSWORD \
--no-daemon
artifacts:
- android/app/build/outputs/apk/release/app-release.apk
android-release-aab:
name: Android Release AAB
max_build_duration: 45
instance_type: mac_mini_m2
environment:
node: 22
java: 21
cache:
cache_paths:
- $HOME/.gradle/caches
- $HOME/.gradle/wrapper
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICES_JSON" ]; then
echo "$GOOGLE_SERVICES_JSON" | base64 --decode > android/app/google-services.json
fi
- name: Capacitor sync
script: npx cap sync android
- name: Set up keystore
script: echo "$CM_KEYSTORE" | base64 --decode > /tmp/keystore.jks
- name: Build Release AAB
script: |
cd android
./gradlew bundleRelease \
-Pandroid.injected.signing.store.file=/tmp/keystore.jks \
-Pandroid.injected.signing.store.password=$CM_KEYSTORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$CM_KEY_ALIAS \
-Pandroid.injected.signing.key.password=$CM_KEY_PASSWORD \
--no-daemon
artifacts:
- android/app/build/outputs/bundle/release/app-release.aab
android-release:
name: Android Publish to Google Play
max_build_duration: 60
instance_type: mac_mini_m2
environment:
node: 22
java: 21
cache:
cache_paths:
- $HOME/.gradle/caches
- $HOME/.gradle/wrapper
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICES_JSON" ]; then
echo "$GOOGLE_SERVICES_JSON" | base64 --decode > android/app/google-services.json
fi
- name: Capacitor sync
script: npx cap sync android
- name: Set up keystore
script: echo "$CM_KEYSTORE" | base64 --decode > /tmp/keystore.jks
- name: Build Release AAB
script: |
cd android
./gradlew bundleRelease \
-Pandroid.injected.signing.store.file=/tmp/keystore.jks \
-Pandroid.injected.signing.store.password=$CM_KEYSTORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$CM_KEY_ALIAS \
-Pandroid.injected.signing.key.password=$CM_KEY_PASSWORD \
--no-daemon
publishing:
google_play:
credentials: $GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS
track: $GOOGLE_PLAY_TRACK
submit_as_draft: false
artifacts:
- android/app/build/outputs/bundle/release/app-release.aab
ios-debug:
name: iOS Debug IPA
max_build_duration: 60
instance_type: mac_mini_m2
environment:
node: 22
xcode: latest
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
- name: Capacitor sync
script: npx cap sync ios
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICE_INFO_PLIST" ]; then
echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist
ruby -e "
require 'xcodeproj'
project = Xcodeproj::Project.open('ios/App/App.xcodeproj')
target = project.targets.find { |t| t.name == 'App' }
app_group = project.main_group['App']
unless app_group.files.find { |f| f.path == 'GoogleService-Info.plist' }
file_ref = app_group.new_reference('GoogleService-Info.plist')
target.resources_build_phase.add_file_reference(file_ref)
project.save
end
"
fi
- name: Capacitor sync
script: npx cap sync ios
- name: Set up signing
script: |
keychain initialize
if [ -n "$APP_STORE_CONNECT_PRIVATE_KEY" ]; then
app-store-connect fetch-signing-files \
$(xcode-project detect-bundle-id) \
--type IOS_APP_DEVELOPMENT \
--certificate-key=@env:APP_STORE_CONNECT_PRIVATE_KEY \
--issuer-id=$APP_STORE_CONNECT_ISSUER_ID \
--key-id=$APP_STORE_CONNECT_KEY_IDENTIFIER \
--create
xcode-project use-profiles
elif [ -n "$CM_CERTIFICATE" ]; then
echo "$CM_CERTIFICATE" | base64 --decode > /tmp/cert.p12
keychain add-certificates \
--certificate /tmp/cert.p12 \
--certificate-password "$CM_CERTIFICATE_PASSWORD"
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
echo "$CM_PROVISIONING_PROFILE" | base64 --decode > "$HOME/Library/MobileDevice/Provisioning Profiles/profile.mobileprovision"
xcode-project use-profiles
else
echo "No signing credentials configured — build will fail at signing"
exit 1
fi
- name: Build IPA
script: |
xcode-project build-ipa \
--workspace ios/App/App.xcworkspace \
--scheme App
artifacts:
- build/ios/ipa/*.ipa
ios-release:
name: iOS Release IPA
max_build_duration: 90
instance_type: mac_mini_m2
environment:
node: 22
xcode: latest
scripts:
- name: Strip unused scaffold packages
script: |
for pkg in "@capacitor/google-maps" "@capacitor/push-notifications" "@capacitor-firebase/authentication"; do
if ! grep -rq "$pkg" src/; then
node -e "const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));delete p.dependencies['${pkg}'];fs.writeFileSync('package.json',JSON.stringify(p,null,2));"
echo "Stripped $pkg (not used in src/)"
else
echo "Keeping $pkg (used in src/)"
fi
done
- name: Install dependencies
script: rm -f package-lock.json && npm install --legacy-peer-deps
- name: Build web assets
script: npm run build
- name: Capacitor sync
script: npx cap sync ios
- name: Write Firebase config
script: |
if [ -n "$GOOGLE_SERVICE_INFO_PLIST" ]; then
echo "$GOOGLE_SERVICE_INFO_PLIST" | base64 --decode > ios/App/App/GoogleService-Info.plist
ruby -e "
require 'xcodeproj'
project = Xcodeproj::Project.open('ios/App/App.xcodeproj')
target = project.targets.find { |t| t.name == 'App' }
app_group = project.main_group['App']
unless app_group.files.find { |f| f.path == 'GoogleService-Info.plist' }
file_ref = app_group.new_reference('GoogleService-Info.plist')
target.resources_build_phase.add_file_reference(file_ref)
project.save
end
"
fi
- name: Capacitor sync
script: npx cap sync ios
- name: Set up signing
script: |
keychain initialize
if [ -n "$APP_STORE_CONNECT_PRIVATE_KEY" ]; then
app-store-connect fetch-signing-files \
$(xcode-project detect-bundle-id) \
--type IOS_APP_STORE \
--certificate-key=@env:APP_STORE_CONNECT_PRIVATE_KEY \
--issuer-id=$APP_STORE_CONNECT_ISSUER_ID \
--key-id=$APP_STORE_CONNECT_KEY_IDENTIFIER \
--create
xcode-project use-profiles
else
echo "$CM_CERTIFICATE" | base64 --decode > /tmp/cert.p12
keychain add-certificates \
--certificate /tmp/cert.p12 \
--certificate-password "$CM_CERTIFICATE_PASSWORD"
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
echo "$CM_PROVISIONING_PROFILE" | base64 --decode > "$HOME/Library/MobileDevice/Provisioning Profiles/profile.mobileprovision"
xcode-project use-profiles
fi
- name: Build IPA
script: |
xcode-project build-ipa \
--workspace ios/App/App.xcworkspace \
--scheme App \
--config Release
- name: Publish
script: |
if [ "$SUBMIT_TO_TESTFLIGHT" = "true" ] || [ "$SUBMIT_TO_APP_STORE" = "true" ]; then
app-store-connect publish \
--certificate-key=@env:APP_STORE_CONNECT_PRIVATE_KEY \
--issuer-id=$APP_STORE_CONNECT_ISSUER_ID \
--key-id=$APP_STORE_CONNECT_KEY_IDENTIFIER \
--submit-to-testflight=$SUBMIT_TO_TESTFLIGHT \
--submit-to-app-store=$SUBMIT_TO_APP_STORE
fi
artifacts:
- build/ios/ipa/*.ipa
+3 -3
View File
@@ -10,7 +10,7 @@
"lint": "eslint" "lint": "eslint"
}, },
"dependencies": { "dependencies": {
"@capacitor-firebase/authentication": "^8.0.0", "@capacitor-firebase/authentication": "^7.0.0",
"@capacitor/android": "8.3.4", "@capacitor/android": "8.3.4",
"@capacitor/app": "8.1.0", "@capacitor/app": "8.1.0",
"@capacitor/core": "8.3.4", "@capacitor/core": "8.3.4",
@@ -21,8 +21,8 @@
"@capacitor/push-notifications": "^8.1.1", "@capacitor/push-notifications": "^8.1.1",
"@capacitor/status-bar": "8.0.2", "@capacitor/status-bar": "8.0.2",
"@ionic/pwa-elements": "^3.0.0", "@ionic/pwa-elements": "^3.0.0",
"@ionic/react": "8.8.7", "@ionic/react": "^8.5.0",
"@ionic/react-router": "8.8.7", "@ionic/react-router": "^8.5.0",
"@supabase/supabase-js": "^2.0.0", "@supabase/supabase-js": "^2.0.0",
"firebase": "^11.0.0", "firebase": "^11.0.0",
"ionicons": "^7.4.0", "ionicons": "^7.4.0",
+18 -25
View File
@@ -1,39 +1,32 @@
import React, { useEffect } from 'react'; import React from "react";
import { Redirect, Route } from 'react-router-dom'; import { Redirect, Route } from "react-router-dom";
import { IonApp, IonRouterOutlet } from '@ionic/react'; import { IonApp, IonRouterOutlet } from "@ionic/react";
import { IonReactRouter } from '@ionic/react-router'; import { IonReactRouter } from "@ionic/react-router";
import { setStatusBarStyle, Style } from './utils/statusBar';
import '@ionic/react/css/core.css'; import "@ionic/react/css/core.css";
import '@ionic/react/css/normalize.css'; import "@ionic/react/css/normalize.css";
import '@ionic/react/css/structure.css'; import "@ionic/react/css/structure.css";
import '@ionic/react/css/typography.css'; import "@ionic/react/css/typography.css";
import '@ionic/react/css/padding.css'; import "@ionic/react/css/padding.css";
import '@ionic/react/css/float-elements.css'; import "@ionic/react/css/float-elements.css";
import '@ionic/react/css/text-alignment.css'; import "@ionic/react/css/text-alignment.css";
import '@ionic/react/css/text-transformation.css'; import "@ionic/react/css/text-transformation.css";
import '@ionic/react/css/flex-utils.css'; import "@ionic/react/css/flex-utils.css";
import '@ionic/react/css/display.css'; import "@ionic/react/css/display.css";
import './theme/variables.css'; import "./theme/variables.css";
import Home from './pages/Home'; import Home from "./pages/Home";
const App: React.FC = () => { const App: React.FC = () => (
useEffect(() => {
setStatusBarStyle(Style.Light);
}, []);
return (
<IonApp> <IonApp>
<IonReactRouter> <IonReactRouter>
<IonRouterOutlet> <IonRouterOutlet>
<Route path="/home" component={Home} exact /> <Route path="/home" component={Home} exact />
<Route exact path="/" render={() => <Redirect to="/home" />} /> <Redirect exact from="/" to="/home" />
</IonRouterOutlet> </IonRouterOutlet>
</IonReactRouter> </IonReactRouter>
</IonApp> </IonApp>
); );
};
export default App; export default App;
+4 -11
View File
@@ -9,20 +9,13 @@ import {
const Home: React.FC = () => ( const Home: React.FC = () => (
<IonPage> <IonPage>
<IonHeader translucent className="home-header"> <IonHeader>
<IonToolbar className="home-toolbar"> <IonToolbar>
<IonTitle>Home</IonTitle> <IonTitle>Home</IonTitle>
</IonToolbar> </IonToolbar>
</IonHeader> </IonHeader>
<IonContent fullscreen className="home-content"> <IonContent className="ion-padding">
<div className="home-shell minimal-home-shell"> <p>Welcome! Start building your app here.</p>
<section className="minimal-welcome-card subtle-welcome-card">
<h1>Welcome to your new app</h1>
<p className="minimal-subtitle">
Chat with the assistant to start adding features and pages
</p>
</section>
</div>
</IonContent> </IonContent>
</IonPage> </IonPage>
); );
+40 -127
View File
@@ -1,152 +1,65 @@
/* Ionic CSS Variables — customise to match your app's brand */ /* Ionic CSS Variables — customise to match your app's brand */
:root { :root {
--ion-color-primary: #5e6ad2; --ion-color-primary: #3880ff;
--ion-color-primary-rgb: 94, 106, 210; --ion-color-primary-rgb: 56, 128, 255;
--ion-color-primary-contrast: #ffffff; --ion-color-primary-contrast: #ffffff;
--ion-color-primary-contrast-rgb: 255, 255, 255; --ion-color-primary-contrast-rgb: 255, 255, 255;
--ion-color-primary-shade: #535db9; --ion-color-primary-shade: #3171e0;
--ion-color-primary-tint: #6e79d7; --ion-color-primary-tint: #4c8dff;
--ion-color-secondary: #7a89f4; --ion-color-secondary: #3dc2ff;
--ion-color-secondary-rgb: 122, 137, 244; --ion-color-secondary-rgb: 61, 194, 255;
--ion-color-secondary-contrast: #ffffff; --ion-color-secondary-contrast: #ffffff;
--ion-color-secondary-contrast-rgb: 255, 255, 255; --ion-color-secondary-contrast-rgb: 255, 255, 255;
--ion-color-secondary-shade: #6b79d7; --ion-color-secondary-shade: #36abe0;
--ion-color-secondary-tint: #8895f5; --ion-color-secondary-tint: #50c8ff;
--ion-color-tertiary: #8f78d8; --ion-color-tertiary: #5260ff;
--ion-color-tertiary-rgb: 143, 120, 216; --ion-color-tertiary-rgb: 82, 96, 255;
--ion-color-tertiary-contrast: #ffffff; --ion-color-tertiary-contrast: #ffffff;
--ion-color-tertiary-contrast-rgb: 255, 255, 255; --ion-color-tertiary-contrast-rgb: 255, 255, 255;
--ion-color-tertiary-shade: #7e6ac0; --ion-color-tertiary-shade: #4854e0;
--ion-color-tertiary-tint: #9a86dc; --ion-color-tertiary-tint: #6370ff;
--ion-color-success: #3aa67a; --ion-color-success: #2dd36f;
--ion-color-success-rgb: 58, 166, 122; --ion-color-success-rgb: 45, 211, 111;
--ion-color-success-contrast: #ffffff; --ion-color-success-contrast: #ffffff;
--ion-color-success-contrast-rgb: 255, 255, 255; --ion-color-success-contrast-rgb: 255, 255, 255;
--ion-color-success-shade: #33926b; --ion-color-success-shade: #28ba62;
--ion-color-success-tint: #4eb088; --ion-color-success-tint: #42d77d;
--ion-color-warning: #dfb25a; --ion-color-warning: #ffc409;
--ion-color-warning-rgb: 223, 178, 90; --ion-color-warning-rgb: 255, 196, 9;
--ion-color-warning-contrast: #2d2520; --ion-color-warning-contrast: #000000;
--ion-color-warning-contrast-rgb: 45, 37, 32; --ion-color-warning-contrast-rgb: 0, 0, 0;
--ion-color-warning-shade: #c49d4f; --ion-color-warning-shade: #e0ac08;
--ion-color-warning-tint: #e2bb6b; --ion-color-warning-tint: #ffca22;
--ion-color-danger: #cf6679; --ion-color-danger: #eb445a;
--ion-color-danger-rgb: 207, 102, 121; --ion-color-danger-rgb: 235, 68, 90;
--ion-color-danger-contrast: #ffffff; --ion-color-danger-contrast: #ffffff;
--ion-color-danger-contrast-rgb: 255, 255, 255; --ion-color-danger-contrast-rgb: 255, 255, 255;
--ion-color-danger-shade: #b65a6a; --ion-color-danger-shade: #cf3c4f;
--ion-color-danger-tint: #d57587; --ion-color-danger-tint: #ed576b;
--ion-color-dark: #1f2430; --ion-color-dark: #222428;
--ion-color-dark-rgb: 31, 36, 48; --ion-color-dark-rgb: 34, 36, 40;
--ion-color-dark-contrast: #ffffff; --ion-color-dark-contrast: #ffffff;
--ion-color-dark-contrast-rgb: 255, 255, 255; --ion-color-dark-contrast-rgb: 255, 255, 255;
--ion-color-dark-shade: #1b202a; --ion-color-dark-shade: #1e2023;
--ion-color-dark-tint: #353946; --ion-color-dark-tint: #383a3e;
--ion-color-medium: #7f8697; --ion-color-medium: #92949c;
--ion-color-medium-rgb: 127, 134, 151; --ion-color-medium-rgb: 146, 148, 156;
--ion-color-medium-contrast: #ffffff; --ion-color-medium-contrast: #ffffff;
--ion-color-medium-contrast-rgb: 255, 255, 255; --ion-color-medium-contrast-rgb: 255, 255, 255;
--ion-color-medium-shade: #707686; --ion-color-medium-shade: #808289;
--ion-color-medium-tint: #8c93a2; --ion-color-medium-tint: #9d9fa6;
--ion-color-light: #f3f5fb; --ion-color-light: #f4f5f8;
--ion-color-light-rgb: 243, 245, 251; --ion-color-light-rgb: 244, 245, 248;
--ion-color-light-contrast: #1f2430; --ion-color-light-contrast: #000000;
--ion-color-light-contrast-rgb: 31, 36, 48; --ion-color-light-contrast-rgb: 0, 0, 0;
--ion-color-light-shade: #d6d8dd; --ion-color-light-shade: #d7d8da;
--ion-color-light-tint: #f4f6fb; --ion-color-light-tint: #f5f6f9;
--app-background: #ffffff;
--app-surface: #ffffff;
--app-surface-secondary: #f6f7fb;
--app-text-primary: #202532;
--app-text-secondary: rgba(32, 37, 50, 0.68);
--app-text-tertiary: rgba(32, 37, 50, 0.46);
--app-accent-soft: rgba(94, 106, 210, 0.12);
--app-accent-softer: rgba(94, 106, 210, 0.08);
--app-success-soft: rgba(58, 166, 122, 0.12);
--app-shadow: 0 18px 48px rgba(82, 95, 140, 0.08);
}
body {
background: var(--app-background);
color: var(--app-text-primary);
}
ion-content.home-content {
--background: var(--app-background);
}
.home-toolbar {
--background: rgba(255, 255, 255, 0.92);
--border-width: 0;
--border-color: transparent;
--color: var(--app-text-primary);
box-shadow: none;
backdrop-filter: blur(18px);
}
ion-header.home-header::after {
display: none;
}
.home-shell {
padding: calc(88px + var(--ion-safe-area-top)) 24px
calc(32px + var(--ion-safe-area-bottom));
display: flex;
flex-direction: column;
}
.minimal-home-shell {
min-height: 100%;
justify-content: flex-start;
}
.minimal-welcome-card {
text-align: left;
display: flex;
flex-direction: column;
gap: 10px;
}
.subtle-welcome-card {
max-width: 420px;
margin: 0;
padding: 28px 24px;
background: var(--app-surface-secondary);
border-radius: 28px;
}
.minimal-welcome-card h1 {
margin: 0;
color: var(--app-text-primary);
font-size: 32px;
line-height: 1.12;
letter-spacing: -0.03em;
font-weight: 700;
}
.minimal-subtitle {
margin: 0;
color: var(--app-text-secondary);
font-size: 15px;
line-height: 1.55;
}
@media (min-width: 680px) {
.home-shell {
max-width: 720px;
margin: 0 auto;
}
.minimal-welcome-card h1 {
font-size: 40px;
}
} }
-3
View File
@@ -1,6 +1,3 @@
// NOTE: @ionic/react and @ionic/react-router are pinned to 8.8.7 in package.json.
// 8.8.8 introduced a regression that breaks IonRouterOutlet page transition animations.
// Do not upgrade until the upstream fix is confirmed.
import { defineConfig, type Plugin } from 'vite'; import { defineConfig, type Plugin } from 'vite';
import react from '@vitejs/plugin-react'; import react from '@vitejs/plugin-react';
+46 -21
View File
@@ -216,16 +216,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@capacitor-firebase/authentication@npm:^8.0.0": "@capacitor-firebase/authentication@npm:^7.0.0":
version: 8.2.0 version: 7.5.0
resolution: "@capacitor-firebase/authentication@npm:8.2.0" resolution: "@capacitor-firebase/authentication@npm:7.5.0"
peerDependencies: peerDependencies:
"@capacitor/core": ">=8.0.0" "@capacitor/core": ">=7.0.0"
firebase: ^12.6.0 firebase: ^11.2.0
peerDependenciesMeta: peerDependenciesMeta:
firebase: firebase:
optional: true optional: true
checksum: 10c0/497c8063e3145ee719dbeb206bd30d7e9581471a7dfa6e6bb3067e96c29468a8035430101abcb0c724bec936e30ca1863344723115ae0b3a9a317e192c0ef3d2 checksum: 10c0/aea4854cd6f8f2282bbbfb5cb0e30dc7152cd593a70c6792a1583fa085803f9330a77584f3ae66ee8c9b65b035374c2fe86545b191d57c0814778b6276306e1e
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1108,6 +1108,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@ionic/core@npm:8.8.8":
version: 8.8.8
resolution: "@ionic/core@npm:8.8.8"
dependencies:
"@stencil/core": "npm:4.43.0"
ionicons: "npm:^8.0.13"
tslib: "npm:^2.1.0"
checksum: 10c0/fea32925aaebec558c1c3bb9c30f8c0806d3480a67936e63cdcce8846138688d9b6b5b853ebe771132f0f79efef16568b17d11495f7997ea325a265a7e7d7af3
languageName: node
linkType: hard
"@ionic/pwa-elements@npm:^3.0.0": "@ionic/pwa-elements@npm:^3.0.0":
version: 3.4.0 version: 3.4.0
resolution: "@ionic/pwa-elements@npm:3.4.0" resolution: "@ionic/pwa-elements@npm:3.4.0"
@@ -1115,22 +1126,36 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@ionic/react-router@npm:8.8.7": "@ionic/react-router@npm:^8.5.0":
version: 8.8.7 version: 8.8.8
resolution: "@ionic/react-router@npm:8.8.7" resolution: "@ionic/react-router@npm:8.8.8"
dependencies: dependencies:
"@ionic/react": "npm:8.8.7" "@ionic/react": "npm:8.8.8"
tslib: "npm:*" tslib: "npm:*"
peerDependencies: peerDependencies:
react: ">=16.8.6" react: ">=16.8.6"
react-dom: ">=16.8.6" react-dom: ">=16.8.6"
react-router: ^5.0.1 react-router: ^5.0.1
react-router-dom: ^5.0.1 react-router-dom: ^5.0.1
checksum: 10c0/302d6ad9c0d450cf6466ff18622aa7708af77c1c4a676d2ff39eca6add440fe96d36a157feae146c3da460c32e7799357320b3270740b050ab040a664b9f0ff2 checksum: 10c0/be9555ec4dbfd0565cada39d42236eb0b9e2283a13f500b42d5c0c06d6198c17a7be385cfb2ce4f9e89236c71992c30169328b861943a3fe7344c672ad94ae0c
languageName: node languageName: node
linkType: hard linkType: hard
"@ionic/react@npm:8.8.7": "@ionic/react@npm:8.8.8":
version: 8.8.8
resolution: "@ionic/react@npm:8.8.8"
dependencies:
"@ionic/core": "npm:8.8.8"
ionicons: "npm:^8.0.13"
tslib: "npm:*"
peerDependencies:
react: ">=16.8.6"
react-dom: ">=16.8.6"
checksum: 10c0/b1b8888f487dc564735adde57ef3cd054e6c9bc38601f133823e69cb98d8e51c99c8902fe48fdd11ee5521ae58b322f110a1fbc8b8fd9bc62e27fc0b806bddd0
languageName: node
linkType: hard
"@ionic/react@npm:^8.5.0":
version: 8.8.7 version: 8.8.7
resolution: "@ionic/react@npm:8.8.7" resolution: "@ionic/react@npm:8.8.7"
dependencies: dependencies:
@@ -1864,9 +1889,9 @@ __metadata:
linkType: hard linkType: hard
"@types/google.maps@npm:^3.53.1, @types/google.maps@npm:^3.58.1": "@types/google.maps@npm:^3.53.1, @types/google.maps@npm:^3.58.1":
version: 3.65.0 version: 3.64.1
resolution: "@types/google.maps@npm:3.65.0" resolution: "@types/google.maps@npm:3.64.1"
checksum: 10c0/d41bc1ed2c63f297a8956b097953515e87aa21d25ef918102067efa97113ea558bb42be521337af93698b36d4c6283439b3e087b4b57c7033f59128cdc7159cb checksum: 10c0/4ade621941045c7e1b1ead30e0b4025b7fccf2b4cfb7c9b5f48c31cceb964c74d17c28b6105be15b99df85c23e19b25415e9fd7bdd7b1d40b7000d22dbbb4e7e
languageName: node languageName: node
linkType: hard linkType: hard
@@ -2007,7 +2032,7 @@ __metadata:
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "app@workspace:." resolution: "app@workspace:."
dependencies: dependencies:
"@capacitor-firebase/authentication": "npm:^8.0.0" "@capacitor-firebase/authentication": "npm:^7.0.0"
"@capacitor/android": "npm:8.3.4" "@capacitor/android": "npm:8.3.4"
"@capacitor/app": "npm:8.1.0" "@capacitor/app": "npm:8.1.0"
"@capacitor/cli": "npm:8.3.4" "@capacitor/cli": "npm:8.3.4"
@@ -2019,8 +2044,8 @@ __metadata:
"@capacitor/push-notifications": "npm:^8.1.1" "@capacitor/push-notifications": "npm:^8.1.1"
"@capacitor/status-bar": "npm:8.0.2" "@capacitor/status-bar": "npm:8.0.2"
"@ionic/pwa-elements": "npm:^3.0.0" "@ionic/pwa-elements": "npm:^3.0.0"
"@ionic/react": "npm:8.8.7" "@ionic/react": "npm:^8.5.0"
"@ionic/react-router": "npm:8.8.7" "@ionic/react-router": "npm:^8.5.0"
"@supabase/supabase-js": "npm:^2.0.0" "@supabase/supabase-js": "npm:^2.0.0"
"@types/katex": "npm:^0.16.0" "@types/katex": "npm:^0.16.0"
"@types/react": "npm:^19.0.0" "@types/react": "npm:^19.0.0"
@@ -2969,8 +2994,8 @@ __metadata:
linkType: hard linkType: hard
"protobufjs@npm:^7.2.5": "protobufjs@npm:^7.2.5":
version: 7.6.2 version: 7.6.1
resolution: "protobufjs@npm:7.6.2" resolution: "protobufjs@npm:7.6.1"
dependencies: dependencies:
"@protobufjs/aspromise": "npm:^1.1.2" "@protobufjs/aspromise": "npm:^1.1.2"
"@protobufjs/base64": "npm:^1.1.2" "@protobufjs/base64": "npm:^1.1.2"
@@ -2984,7 +3009,7 @@ __metadata:
"@protobufjs/utf8": "npm:^1.1.1" "@protobufjs/utf8": "npm:^1.1.1"
"@types/node": "npm:>=13.7.0" "@types/node": "npm:>=13.7.0"
long: "npm:^5.3.2" long: "npm:^5.3.2"
checksum: 10c0/3c552dfe3cbcfad2d6c312a76cd189cf5be9fb36b203f6292f79c6020d675f7f33d5531ce312441c42ae75deb24ced32760e64fe4aa3d5b3c2295fd67cea270c checksum: 10c0/364c6914facac19ace915e353f71c5d5996bfa8177a3a68c09bd2513a3ecf780538aca06cb3439237f50489db2fae321c4a4db60fd7f9ec65315b7ad66bea029
languageName: node languageName: node
linkType: hard linkType: hard