Skip to content

Commit e04334a

Browse files
author
Lalit Sharma
committed
feat: update changelog for version 1.1.46, fix Android warm-start share-intent persistence, and add debug instrumentation for share-intake paths
1 parent 7f5bca9 commit e04334a

5 files changed

Lines changed: 73 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.1.46] — 2026-02-27
9+
10+
### Fixed
11+
- Fixed Android warm-start share-intent persistence by caching incoming `ACTION_SEND` intents in `MainActivity.onNewIntent`, so pending share payloads remain retrievable from JS after app resume.
12+
13+
### Added
14+
- Added temporary `[share.debug]` instrumentation in share-intake paths (`useShareIntentBridge` + `RootNavigator`) to expose raw/parsed share payloads and map-link parse outcomes in logcat.
15+
16+
### Changed
17+
- Bumped `apps/mobile` version to `1.1.46`.
18+
819
## [1.1.45] — 2026-02-27
920

1021
### Fixed

apps/mobile/android/app/src/main/java/com/lallimaven/eclipsetimer/MainActivity.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import expo.modules.splashscreen.SplashScreenManager
33

44
import android.os.Build
55
import android.os.Bundle
6+
import android.content.Intent
67

78
import com.facebook.react.ReactActivity
89
import com.facebook.react.ReactActivityDelegate
910
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
1011
import com.facebook.react.defaults.DefaultReactActivityDelegate
1112

1213
import expo.modules.ReactActivityDelegateWrapper
14+
import expo.modules.shareintent.ExpoShareIntentSingleton
1315

1416
class MainActivity : ReactActivity() {
1517
override fun onCreate(savedInstanceState: Bundle?) {
@@ -44,6 +46,18 @@ class MainActivity : ReactActivity() {
4446
){})
4547
}
4648

49+
override fun onNewIntent(intent: Intent?) {
50+
super.onNewIntent(intent)
51+
if (intent == null) return
52+
53+
setIntent(intent)
54+
if (intent.type != null) {
55+
// Keep the latest share intent pending so JS can retrieve it reliably after resume.
56+
ExpoShareIntentSingleton.intent = intent
57+
ExpoShareIntentSingleton.isPending = true
58+
}
59+
}
60+
4761
/**
4862
* Align the back button behavior with Android S
4963
* where moving root activities to background instead of finishing activities.

apps/mobile/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@eclipse-timer/mobile",
3-
"version": "1.1.45",
3+
"version": "1.1.46",
44
"private": true,
55
"main": "index.js",
66
"scripts": {

apps/mobile/src/navigation/RootNavigator.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ function TimerRoute({
410410
if (!pendingSharedLocation) return;
411411
if (lastAppliedSharedLocationIdRef.current === pendingSharedLocation.id) return;
412412

413+
console.info("[share.debug] applying_pending_location", pendingSharedLocation);
413414
lastAppliedSharedLocationIdRef.current = pendingSharedLocation.id;
414415
timerState.jumpTo(pendingSharedLocation.lat, pendingSharedLocation.lon, 2);
415416
timerState.setStatusMessage("Location loaded from shared map link");
@@ -609,6 +610,7 @@ export default function RootNavigator() {
609610
const { state: appState, hasHydratedPreferences, actions } = useAppState();
610611
const { colors, resolvedTheme } = useAppTheme();
611612
const { hasShareIntent, shareIntent, resetShareIntent } = useShareIntentBridge({
613+
debug: true,
612614
resetOnBackground: false,
613615
});
614616
const navigationRef = useNavigationContainerRef<RootStackParamList>();
@@ -735,6 +737,7 @@ export default function RootNavigator() {
735737
id: `shared-location-${sharedLocationSequenceRef.current}`,
736738
};
737739

740+
console.info("[share.debug] queue_pending_location", pending);
738741
setPendingSharedLocation(pending);
739742
closeMenu();
740743

@@ -770,12 +773,15 @@ export default function RootNavigator() {
770773

771774
const handleIncomingUrl = useCallback(
772775
async (incoming: IncomingExternalLink) => {
776+
console.info("[share.debug] handle_incoming", incoming);
773777
if (!shouldProcessIncomingExternalLink(incoming.value)) {
778+
console.info("[share.debug] dropped_duplicate", incoming.value);
774779
return false;
775780
}
776781

777782
const action = parseFeaturedEclipseDeepLink(incoming.value);
778783
if (action) {
784+
console.info("[share.debug] featured_deep_link", action);
779785
if (!navigationRef.isReady()) {
780786
pendingFeaturedDeepLinkActionRef.current = action;
781787
return true;
@@ -786,7 +792,12 @@ export default function RootNavigator() {
786792
}
787793

788794
const sharedMapLink = await parseSharedMapLinkAsync(incoming.value);
789-
if (!sharedMapLink) return false;
795+
if (!sharedMapLink) {
796+
console.info("[share.debug] map_parse_failed", incoming.value);
797+
return false;
798+
}
799+
800+
console.info("[share.debug] map_parse_success", sharedMapLink);
790801

791802
queuePendingSharedLocation(sharedMapLink);
792803
return true;
@@ -933,6 +944,15 @@ export default function RootNavigator() {
933944
text: shareIntent.text,
934945
value: shareIntent.meta?.title,
935946
});
947+
console.info("[share.debug] share_payload", {
948+
hasShareIntent,
949+
text: shareIntent.text,
950+
webUrl: shareIntent.webUrl,
951+
title: shareIntent.meta?.title,
952+
type: shareIntent.type,
953+
fileCount: shareIntent.files?.length ?? 0,
954+
normalized: shareIncomingLinks.map((x) => x.value),
955+
});
936956
if (!shareIncomingLinks.length) {
937957
resetShareIntent();
938958
return;

apps/mobile/src/services/useShareIntentBridge.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ export default function useShareIntentBridge(options: ShareIntentOptions = {}) {
5353
],
5454
);
5555

56+
const logDebug = useCallback(
57+
(...args: unknown[]) => {
58+
if (!resolvedOptions.debug) return;
59+
console.info("[share.debug]", ...args);
60+
},
61+
[resolvedOptions.debug],
62+
);
63+
5664
const resetShareIntent = useCallback(
5765
(clearNativeModule = true) => {
5866
if (resolvedOptions.disabled) return;
@@ -71,6 +79,7 @@ export default function useShareIntentBridge(options: ShareIntentOptions = {}) {
7179
const refreshShareIntent = useCallback(() => {
7280
if (resolvedOptions.disabled || !ShareIntentModule) return;
7381

82+
logDebug("refresh", { platform: Platform.OS, url });
7483
if (Platform.OS === "android") {
7584
ShareIntentModule.getShareIntent("");
7685
return;
@@ -80,7 +89,7 @@ export default function useShareIntentBridge(options: ShareIntentOptions = {}) {
8089
if (typeof url === "string" && url.includes(`${scheme}://dataUrl=`)) {
8190
ShareIntentModule.getShareIntent(url);
8291
}
83-
}, [resolvedOptions, url]);
92+
}, [logDebug, resolvedOptions, url]);
8493

8594
useEffect(() => {
8695
if (resolvedOptions.disabled) {
@@ -90,50 +99,61 @@ export default function useShareIntentBridge(options: ShareIntentOptions = {}) {
9099

91100
if (!ShareIntentModule) {
92101
setIsReady(true);
93-
if (resolvedOptions.debug) {
94-
console.warn("expo-share-intent module unavailable");
95-
}
102+
console.warn("[share.debug] expo-share-intent module unavailable");
96103
return;
97104
}
98105

99106
const changeSubscription = ShareIntentModule.addListener("onChange", (event) => {
100107
try {
108+
logDebug("onChange_raw", event?.value);
101109
const parsed = parseShareIntent(
102110
event.value as string | AndroidShareIntent,
103111
resolvedOptions,
104112
);
113+
logDebug("onChange_parsed", {
114+
text: parsed.text,
115+
webUrl: parsed.webUrl,
116+
title: parsed.meta?.title,
117+
type: parsed.type,
118+
fileCount: parsed.files?.length ?? 0,
119+
});
105120
setShareIntent(parsed);
106121
setError(null);
107122
} catch {
123+
logDebug("onChange_parse_error");
108124
setError("Cannot parse share intent value!");
109125
}
110126
});
111127

112128
const errorSubscription = ShareIntentModule.addListener("onError", (event) => {
129+
logDebug("onError", event?.value);
113130
setError(event?.value ?? "Share intent error");
114131
});
115132

116133
// Important: refresh after listeners are attached so cold-start payloads are not dropped.
117134
refreshShareIntent();
135+
logDebug("listeners_ready");
118136
setIsReady(true);
119137

120138
return () => {
121139
changeSubscription.remove();
122140
errorSubscription.remove();
123141
};
124-
}, [refreshShareIntent, resolvedOptions]);
142+
}, [logDebug, refreshShareIntent, resolvedOptions]);
125143

126144
useEffect(() => {
127145
if (resolvedOptions.disabled) return;
128146

129147
const subscription = AppState.addEventListener("change", (nextAppState) => {
130148
if (nextAppState === "active") {
149+
logDebug("appstate_active_refresh");
131150
refreshShareIntent();
132151
} else if (
133152
resolvedOptions.resetOnBackground !== false &&
134153
appState.current === "active" &&
135154
(nextAppState === "inactive" || nextAppState === "background")
136155
) {
156+
logDebug("appstate_background_reset");
137157
resetShareIntent();
138158
}
139159
appState.current = nextAppState;
@@ -142,7 +162,7 @@ export default function useShareIntentBridge(options: ShareIntentOptions = {}) {
142162
return () => {
143163
subscription.remove();
144164
};
145-
}, [refreshShareIntent, resetShareIntent, resolvedOptions]);
165+
}, [logDebug, refreshShareIntent, resetShareIntent, resolvedOptions]);
146166

147167
return {
148168
isReady,

0 commit comments

Comments
 (0)