Skip to content

Commit a804794

Browse files
authored
Merge pull request #374 from KraLeoD/feature/mergeUpstream
Android app changes + fixes, first steps for iOS
2 parents b4ac192 + e6eaedd commit a804794

File tree

21 files changed

+1429
-401
lines changed

21 files changed

+1429
-401
lines changed

SparkyFitnessMobile/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.npm-cache/*
2+
Podfile.lock

SparkyFitnessMobile/App.tsx

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,37 @@
11
import React, { useEffect } from 'react';
2-
import { StatusBar, StyleSheet, useColorScheme } from 'react-native';
3-
import { NavigationContainer } from '@react-navigation/native';
2+
import { StatusBar, StyleSheet, View, Text } from 'react-native';
3+
import { NavigationContainer, DefaultTheme, DarkTheme } from '@react-navigation/native';
44
import { createStackNavigator } from '@react-navigation/stack';
5+
import AsyncStorage from '@react-native-async-storage/async-storage';
56

67
import MainScreen from './src/screens/MainScreen';
78
import SettingsScreen from './src/screens/SettingsScreen';
89
import LogScreen from './src/screens/LogScreen';
910
import { configureBackgroundSync } from './src/services/backgroundSyncService';
11+
import { ThemeProvider, useTheme } from './src/contexts/ThemeContext';
1012

1113
const Stack = createStackNavigator();
1214

13-
function App() {
14-
const isDarkMode = useColorScheme() === 'dark';
15+
function AppContent() {
16+
const { isDarkMode } = useTheme();
1517

1618
useEffect(() => {
17-
configureBackgroundSync();
19+
// Reset the auto-open flag on every app start
20+
const initializeApp = async () => {
21+
// Remove the flag so the dashboard will auto-open on first MainScreen visit
22+
await AsyncStorage.removeItem('@HealthConnect:hasAutoOpenedDashboard');
23+
};
24+
25+
initializeApp();
26+
27+
// Configure background sync without blocking app startup
28+
configureBackgroundSync().catch(error => {
29+
console.error('[App] Failed to configure background sync:', error);
30+
});
1831
}, []);
1932

2033
return (
21-
<NavigationContainer>
34+
<NavigationContainer theme={isDarkMode ? DarkTheme : DefaultTheme}>
2235
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
2336
<Stack.Navigator initialRouteName="Home">
2437
<Stack.Screen name="Home" component={MainScreen} options={{ headerShown: false }} />
@@ -29,6 +42,14 @@ function App() {
2942
);
3043
}
3144

45+
function App() {
46+
return (
47+
<ThemeProvider>
48+
<AppContent />
49+
</ThemeProvider>
50+
);
51+
}
52+
3253
const styles = StyleSheet.create({
3354
// No specific styles needed here as screens will define their own
3455
});

SparkyFitnessMobile/android/app/build.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ apply plugin: "com.android.application"
22
apply plugin: "org.jetbrains.kotlin.android"
33
apply plugin: "com.facebook.react"
44

5+
configurations.all {
6+
resolutionStrategy {
7+
force 'androidx.browser:browser:1.8.0'
8+
}
9+
}
10+
511
/**
612
* This is the configuration block to customize your React Native Android app.
713
* By default you don't need to apply any configuration, just uncomment the lines you need.
@@ -127,6 +133,7 @@ repositories {
127133
dependencies {
128134
// The version of react-native is set by the React Native Gradle Plugin
129135
implementation("com.facebook.react:react-android")
136+
implementation("androidx.browser:browser:1.8.0")
130137

131138
if (hermesEnabled.toBoolean()) {
132139
implementation("com.facebook.react:hermes-android")

SparkyFitnessMobile/android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ buildscript {
22
ext {
33
buildToolsVersion = "35.0.0"
44
minSdkVersion = 26
5-
compileSdkVersion = 35
5+
compileSdkVersion = 36
66
targetSdkVersion = 35
77
ndkVersion = "27.1.12297006"
88
kotlinVersion = "2.1.20"

SparkyFitnessMobile/app.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"name": "SparkyFitness",
2+
"name": "SparkyFitnessMobile",
33
"displayName": "SparkyFitness"
4-
}
4+
}

SparkyFitnessMobile/ios/Podfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ require Pod::Executable.execute_command('node', ['-p',
88
platform :ios, min_ios_version_supported
99
prepare_react_native_project!
1010

11+
# Add NitroModules support for @kingstinct/react-native-healthkit
12+
pod 'NitroModules', :path => '../node_modules/react-native-nitro-modules'
13+
1114
linkage = ENV['USE_FRAMEWORKS']
1215
if linkage != nil
1316
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
@@ -31,5 +34,19 @@ target 'SparkyFitnessMobile' do
3134
:mac_catalyst_enabled => false,
3235
# :ccache_enabled => true
3336
)
37+
38+
# Fix for "Multiple commands produce" error with privacy manifests
39+
# Remove duplicate privacy bundle targets
40+
installer.pods_project.targets.each do |target|
41+
if target.name.end_with?('-React-Core_privacy') && target.name.include?('common')
42+
target.remove_from_project
43+
end
44+
45+
target.build_configurations.each do |config|
46+
config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""
47+
config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
48+
config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
49+
end
50+
end
3451
end
3552
end

SparkyFitnessMobile/ios/SparkyFitnessMobile.xcodeproj/project.pbxproj

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,15 @@
1111
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
1212
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
1313
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
14+
D5766D8D8D1E70B623804AD4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
1415
/* End PBXBuildFile section */
1516

16-
/* Begin PBXContainerItemProxy section */
17-
00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
18-
isa = PBXContainerItemProxy;
19-
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
20-
proxyType = 1;
21-
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
22-
remoteInfo = SparkyFitnessMobile;
23-
};
24-
/* End PBXContainerItemProxy section */
25-
2617
/* Begin PBXFileReference section */
27-
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
2818
13B07F961A680F5B00A75B9A /* SparkyFitnessMobile.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SparkyFitnessMobile.app; sourceTree = BUILT_PRODUCTS_DIR; };
2919
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = SparkyFitnessMobile/Images.xcassets; sourceTree = "<group>"; };
3020
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = SparkyFitnessMobile/Info.plist; sourceTree = "<group>"; };
3121
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = SparkyFitnessMobile/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
22+
17D102262ED90CE4009AB798 /* SparkyFitnessMobile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = SparkyFitnessMobile.entitlements; path = SparkyFitnessMobile/SparkyFitnessMobile.entitlements; sourceTree = "<group>"; };
3223
3B4392A12AC88292D35C810B /* Pods-SparkyFitnessMobile.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SparkyFitnessMobile.debug.xcconfig"; path = "Target Support Files/Pods-SparkyFitnessMobile/Pods-SparkyFitnessMobile.debug.xcconfig"; sourceTree = "<group>"; };
3324
5709B34CF0A7D63546082F79 /* Pods-SparkyFitnessMobile.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SparkyFitnessMobile.release.xcconfig"; path = "Target Support Files/Pods-SparkyFitnessMobile/Pods-SparkyFitnessMobile.release.xcconfig"; sourceTree = "<group>"; };
3425
5DCACB8F33CDC322A6C60F78 /* libPods-SparkyFitnessMobile.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SparkyFitnessMobile.a"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -49,17 +40,10 @@
4940
/* End PBXFrameworksBuildPhase section */
5041

5142
/* Begin PBXGroup section */
52-
00E356F01AD99517003FC87E /* Supporting Files */ = {
53-
isa = PBXGroup;
54-
children = (
55-
00E356F11AD99517003FC87E /* Info.plist */,
56-
);
57-
name = "Supporting Files";
58-
sourceTree = "<group>";
59-
};
6043
13B07FAE1A68108700A75B9A /* SparkyFitnessMobile */ = {
6144
isa = PBXGroup;
6245
children = (
46+
17D102262ED90CE4009AB798 /* SparkyFitnessMobile.entitlements */,
6347
13B07FB51A68108700A75B9A /* Images.xcassets */,
6448
761780EC2CA45674006654EE /* AppDelegate.swift */,
6549
13B07FB61A68108700A75B9A /* Info.plist */,
@@ -172,19 +156,13 @@
172156
/* End PBXProject section */
173157

174158
/* Begin PBXResourcesBuildPhase section */
175-
00E356EC1AD99517003FC87E /* Resources */ = {
176-
isa = PBXResourcesBuildPhase;
177-
buildActionMask = 2147483647;
178-
files = (
179-
);
180-
runOnlyForDeploymentPostprocessing = 0;
181-
};
182159
13B07F8E1A680F5B00A75B9A /* Resources */ = {
183160
isa = PBXResourcesBuildPhase;
184161
buildActionMask = 2147483647;
185162
files = (
186163
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
187164
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
165+
D5766D8D8D1E70B623804AD4 /* PrivacyInfo.xcprivacy in Resources */,
188166
);
189167
runOnlyForDeploymentPostprocessing = 0;
190168
};
@@ -215,10 +193,14 @@
215193
inputFileListPaths = (
216194
"${PODS_ROOT}/Target Support Files/Pods-SparkyFitnessMobile/Pods-SparkyFitnessMobile-frameworks-${CONFIGURATION}-input-files.xcfilelist",
217195
);
196+
inputPaths = (
197+
);
218198
name = "[CP] Embed Pods Frameworks";
219199
outputFileListPaths = (
220200
"${PODS_ROOT}/Target Support Files/Pods-SparkyFitnessMobile/Pods-SparkyFitnessMobile-frameworks-${CONFIGURATION}-output-files.xcfilelist",
221201
);
202+
outputPaths = (
203+
);
222204
runOnlyForDeploymentPostprocessing = 0;
223205
shellPath = /bin/sh;
224206
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SparkyFitnessMobile/Pods-SparkyFitnessMobile-frameworks.sh\"\n";
@@ -254,10 +236,14 @@
254236
inputFileListPaths = (
255237
"${PODS_ROOT}/Target Support Files/Pods-SparkyFitnessMobile/Pods-SparkyFitnessMobile-resources-${CONFIGURATION}-input-files.xcfilelist",
256238
);
239+
inputPaths = (
240+
);
257241
name = "[CP] Copy Pods Resources";
258242
outputFileListPaths = (
259243
"${PODS_ROOT}/Target Support Files/Pods-SparkyFitnessMobile/Pods-SparkyFitnessMobile-resources-${CONFIGURATION}-output-files.xcfilelist",
260244
);
245+
outputPaths = (
246+
);
261247
runOnlyForDeploymentPostprocessing = 0;
262248
shellPath = /bin/sh;
263249
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SparkyFitnessMobile/Pods-SparkyFitnessMobile-resources.sh\"\n";
@@ -276,22 +262,16 @@
276262
};
277263
/* End PBXSourcesBuildPhase section */
278264

279-
/* Begin PBXTargetDependency section */
280-
00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
281-
isa = PBXTargetDependency;
282-
target = 13B07F861A680F5B00A75B9A /* SparkyFitnessMobile */;
283-
targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
284-
};
285-
/* End PBXTargetDependency section */
286-
287265
/* Begin XCBuildConfiguration section */
288266
13B07F941A680F5B00A75B9A /* Debug */ = {
289267
isa = XCBuildConfiguration;
290268
baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-SparkyFitnessMobile.debug.xcconfig */;
291269
buildSettings = {
292270
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
293271
CLANG_ENABLE_MODULES = YES;
272+
CODE_SIGN_ENTITLEMENTS = SparkyFitnessMobile/SparkyFitnessMobile.entitlements;
294273
CURRENT_PROJECT_VERSION = 1;
274+
DEVELOPMENT_TEAM = KR2S32CA88;
295275
ENABLE_BITCODE = NO;
296276
INFOPLIST_FILE = SparkyFitnessMobile/Info.plist;
297277
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
@@ -319,7 +299,9 @@
319299
buildSettings = {
320300
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
321301
CLANG_ENABLE_MODULES = YES;
302+
CODE_SIGN_ENTITLEMENTS = SparkyFitnessMobile/SparkyFitnessMobile.entitlements;
322303
CURRENT_PROJECT_VERSION = 1;
304+
DEVELOPMENT_TEAM = KR2S32CA88;
323305
INFOPLIST_FILE = SparkyFitnessMobile/Info.plist;
324306
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
325307
LD_RUNPATH_SEARCH_PATHS = (
@@ -408,7 +390,11 @@
408390
"-DFOLLY_CFG_NO_COROUTINES=1",
409391
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
410392
);
393+
OTHER_LDFLAGS = "$(inherited) ";
394+
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
411395
SDKROOT = iphoneos;
396+
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
397+
USE_HERMES = true;
412398
};
413399
name = Debug;
414400
};
@@ -473,7 +459,10 @@
473459
"-DFOLLY_CFG_NO_COROUTINES=1",
474460
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
475461
);
462+
OTHER_LDFLAGS = "$(inherited) ";
463+
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
476464
SDKROOT = iphoneos;
465+
USE_HERMES = true;
477466
VALIDATE_PRODUCT = YES;
478467
};
479468
name = Release;

SparkyFitnessMobile/ios/SparkyFitnessMobile.xcworkspace/contents.xcworkspacedata

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SparkyFitnessMobile/ios/SparkyFitnessMobile/Info.plist

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
44
<dict>
5+
<key>BGTaskSchedulerPermittedIdentifiers</key>
6+
<array>
7+
<string>com.transistorsoft.fetch</string>
8+
<string>healthDataSync</string>
9+
</array>
510
<key>CFBundleDevelopmentRegion</key>
611
<string>en</string>
712
<key>CFBundleDisplayName</key>
@@ -26,14 +31,24 @@
2631
<true/>
2732
<key>NSAppTransportSecurity</key>
2833
<dict>
29-
<!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
3034
<key>NSAllowsArbitraryLoads</key>
3135
<false/>
3236
<key>NSAllowsLocalNetworking</key>
3337
<true/>
3438
</dict>
39+
<key>NSHealthShareUsageDescription</key>
40+
<string>This app needs access to your health data to track and sync your fitness metrics including steps, heart rate, calories, weight, and other health information to help you monitor your wellness goals.</string>
41+
<key>NSHealthUpdateUsageDescription</key>
42+
<string>This app may write health data to HealthKit for tracking purposes.</string>
3543
<key>NSLocationWhenInUseUsageDescription</key>
3644
<string></string>
45+
<key>RCTNewArchEnabled</key>
46+
<true/>
47+
<key>UIBackgroundModes</key>
48+
<array>
49+
<string>fetch</string>
50+
<string>processing</string>
51+
</array>
3752
<key>UILaunchStoryboardName</key>
3853
<string>LaunchScreen</string>
3954
<key>UIRequiredDeviceCapabilities</key>

0 commit comments

Comments
 (0)