capacitor-lottie-splash 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -101,9 +101,9 @@ The documented HeadCount defaults are light `#f0f0f0 → #f5f5f5` and dark `#1e1
101
101
 
102
102
  ## Recovery and accessibility
103
103
 
104
- When playback completes before readiness, its final frame holds. After one second, a subtle indeterminate progress rail appears beneath the mark. After 15 foreground seconds the rail stops and a native/browser recovery surface presents “Still starting…” and “Try again.” The native retry reloads the WebView, so it does not depend on JavaScript having already loaded. Reduced-motion and asset failures retain the theme-matched native cover instead of exposing a blank screen.
104
+ When playback completes before readiness, its final frame holds. After one second, a subtle indeterminate progress rail appears beneath the mark and remains visible until the application is ready. Reduced-motion and asset failures retain the theme-matched native cover instead of exposing a blank screen.
105
105
 
106
- For a staged native/over-the-air rollout, the consuming app must keep its web bundle and native host compatible. The native cover stays visible until the app-ready latch is set; a broken boot transitions to the visible recovery surface instead of exposing a blank page.
106
+ For a staged native/over-the-air rollout, the consuming app must keep its web bundle and native host compatible. The native cover stays visible until the app-ready latch is set.
107
107
 
108
108
  ## Compatibility
109
109
 
@@ -12,10 +12,7 @@ import android.view.View
12
12
  import android.view.ViewGroup
13
13
  import android.view.animation.AccelerateDecelerateInterpolator
14
14
  import android.view.animation.LinearInterpolator
15
- import android.widget.Button
16
15
  import android.widget.FrameLayout
17
- import android.widget.LinearLayout
18
- import android.widget.TextView
19
16
  import com.airbnb.lottie.LottieAnimationView
20
17
  import com.airbnb.lottie.LottieCompositionFactory
21
18
  import androidx.activity.ComponentActivity
@@ -23,7 +20,7 @@ import java.util.UUID
23
20
  import kotlin.math.max
24
21
  import kotlin.math.roundToInt
25
22
 
26
- enum class AndroidSplashPhase { PREPARING, PLAYING, HOLDING, HIDING, HIDDEN, RECOVERY }
23
+ enum class AndroidSplashPhase { PREPARING, PLAYING, HOLDING, HIDING, HIDDEN }
27
24
  enum class AndroidSplashPlayback { PLAY, HOLD_FINAL_FRAME }
28
25
 
29
26
  /** A small indeterminate rail that reads as loading without covering the finished logo. */
@@ -82,7 +79,6 @@ object LottieSplashCoordinator {
82
79
  // incorrectly dismissing a healthy native cover during that startup work.
83
80
  private const val WEB_ADOPTION_GRACE_MS = 30_000L
84
81
  private const val PROGRESS_DELAY_MS = 1_000L
85
- private const val RECOVERY_DELAY_MS = 15_000L
86
82
  private const val COVER_FADE_OUT_MS = 500L
87
83
  private val main = Handler(Looper.getMainLooper())
88
84
 
@@ -94,8 +90,6 @@ object LottieSplashCoordinator {
94
90
  private var compositionReady = false
95
91
  private var requestedPlayback = AndroidSplashPlayback.PLAY
96
92
  private var loadingRail: LottieSplashLoadingRail? = null
97
- private var recoveryMessage: TextView? = null
98
- private var recoveryRetry: Button? = null
99
93
  private var presentationId: String? = null
100
94
  private var phase = AndroidSplashPhase.HIDDEN
101
95
  private var playbackSettled = false
@@ -106,16 +100,13 @@ object LottieSplashCoordinator {
106
100
  private var completion: ((String, String?) -> Unit)? = null
107
101
  private var pendingHide: ((Throwable?) -> Unit)? = null
108
102
  private var progressTask: Runnable? = null
109
- private var recoveryTask: Runnable? = null
110
103
  private var adoptionTask: Runnable? = null
111
104
  private var adoptedByWeb = false
112
105
  private var progressRemainingMs = PROGRESS_DELAY_MS
113
- private var recoveryRemainingMs = RECOVERY_DELAY_MS
114
106
  private var waitingClockStartedAtMs = 0L
115
107
  private var waitingClockRunning = false
116
108
 
117
109
  var onStateChange: (() -> Unit)? = null
118
- var onRecoveryRequested: (() -> Unit)? = null
119
110
 
120
111
  /**
121
112
  * Called by AndroidX while deciding whether its system-owned launch surface may leave.
@@ -153,8 +144,6 @@ object LottieSplashCoordinator {
153
144
  playbackOutcome = "static-fallback"
154
145
  playbackReason = null
155
146
  loadingRail = null
156
- recoveryMessage = null
157
- recoveryRetry = null
158
147
 
159
148
  val backgroundStart = if (darkTheme) Color.rgb(30, 30, 30) else Color.rgb(240, 240, 240)
160
149
  root.setBackgroundColor(backgroundStart)
@@ -354,7 +343,6 @@ object LottieSplashCoordinator {
354
343
  private fun resetWaitingUi(id: String) {
355
344
  cancelWaitingTasks()
356
345
  progressRemainingMs = PROGRESS_DELAY_MS
357
- recoveryRemainingMs = RECOVERY_DELAY_MS
358
346
  scheduleWaitingUi(id)
359
347
  }
360
348
 
@@ -371,24 +359,19 @@ object LottieSplashCoordinator {
371
359
  waitingClockRunning = true
372
360
  waitingClockStartedAtMs = SystemClock.elapsedRealtime()
373
361
  progressTask = Runnable { showLoadingRail(id) }
374
- recoveryTask = Runnable { showRecovery(id) }
375
362
  if (loadingRail == null) main.postDelayed(progressTask!!, progressRemainingMs)
376
- main.postDelayed(recoveryTask!!, recoveryRemainingMs)
377
363
  }
378
364
 
379
365
  private fun pauseWaitingClock() {
380
366
  if (!waitingClockRunning) return
381
367
  val elapsed = SystemClock.elapsedRealtime() - waitingClockStartedAtMs
382
368
  progressRemainingMs = max(0, progressRemainingMs - elapsed)
383
- recoveryRemainingMs = max(0, recoveryRemainingMs - elapsed)
384
369
  cancelWaitingTasks()
385
370
  }
386
371
 
387
372
  private fun cancelWaitingTasks() {
388
373
  progressTask?.let(main::removeCallbacks)
389
- recoveryTask?.let(main::removeCallbacks)
390
374
  progressTask = null
391
- recoveryTask = null
392
375
  waitingClockRunning = false
393
376
  }
394
377
 
@@ -404,36 +387,10 @@ object LottieSplashCoordinator {
404
387
  }
405
388
  }
406
389
 
407
- private fun showRecovery(id: String) {
408
- recoveryRemainingMs = 0
409
- if (presentationId != id || appReady || phase != AndroidSplashPhase.HOLDING) return
410
- cancelWaitingTasks()
411
- phase = AndroidSplashPhase.RECOVERY
412
- loadingRail?.visibility = View.GONE
413
- val context = cover?.context ?: return
414
- val textColor = if (darkTheme) Color.WHITE else Color.rgb(30, 30, 30)
415
- val message = TextView(context).apply { text = "Still starting…"; textSize = 16f; setTextColor(textColor); gravity = Gravity.CENTER }
416
- val retry = Button(context).apply { text = "Try again"; setOnClickListener { onRecoveryRequested?.invoke() } }
417
- val recoveryGroup = LinearLayout(context).apply {
418
- orientation = LinearLayout.VERTICAL
419
- gravity = Gravity.CENTER_HORIZONTAL
420
- addView(message)
421
- addView(retry)
422
- }
423
- recoveryMessage = message
424
- recoveryRetry = retry
425
- cover?.addView(recoveryGroup, FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL or Gravity.BOTTOM).apply { bottomMargin = dp(recoveryGroup, 48) })
426
- recoveryGroup.announceForAccessibility("Still starting. Try again is available.")
427
- emit()
428
- }
429
-
430
390
  private fun clearWaitingUi() {
431
391
  cancelWaitingTasks()
432
392
  loadingRail?.let { cover?.removeView(it) }
433
- recoveryMessage?.parent?.let { parent -> (parent as? ViewGroup)?.let { cover?.removeView(it) } }
434
393
  loadingRail = null
435
- recoveryMessage = null
436
- recoveryRetry = null
437
394
  }
438
395
 
439
396
  private fun dismiss(callback: (Throwable?) -> Unit) {
@@ -464,8 +421,6 @@ object LottieSplashCoordinator {
464
421
  animation = null
465
422
  hostActivity = null
466
423
  loadingRail = null
467
- recoveryMessage = null
468
- recoveryRetry = null
469
424
  presentationId = null
470
425
  phase = AndroidSplashPhase.HIDDEN
471
426
  compositionReady = false
@@ -20,7 +20,6 @@ class LottieSplashPlugin : Plugin() {
20
20
  }
21
21
  override fun load() {
22
22
  LottieSplashCoordinator.onStateChange = { notifyListeners("stateChange", stateObject()) }
23
- LottieSplashCoordinator.onRecoveryRequested = { bridge?.webView?.reload() }
24
23
  }
25
24
 
26
25
  @PluginMethod
@@ -89,7 +88,7 @@ class LottieSplashPlugin : Plugin() {
89
88
  webView.postVisualStateCallback(SystemClock.uptimeMillis(), object : WebView.VisualStateCallback() {
90
89
  override fun onComplete(requestId: Long) = finishHandoff()
91
90
  })
92
- // A stalled GPU/compositor must not leave an app-ready screen in recovery.
91
+ // A stalled GPU/compositor must not leave an app-ready screen covered.
93
92
  main.postDelayed(fallback, VISUAL_STATE_TIMEOUT_MS)
94
93
  } catch (_: Throwable) {
95
94
  finishHandoff()
@@ -1,6 +1,6 @@
1
1
  import type { PluginListenerHandle } from '@capacitor/core';
2
2
  export type SplashRenderer = 'ios' | 'android' | 'web';
3
- export type SplashPhase = 'preparing' | 'playing' | 'holding' | 'hiding' | 'hidden' | 'recovery';
3
+ export type SplashPhase = 'preparing' | 'playing' | 'holding' | 'hiding' | 'hidden';
4
4
  export type PlaybackOutcome = 'completed' | 'reduced-motion' | 'static-fallback';
5
5
  export type SplashTheme = 'light' | 'dark';
6
6
  export interface SplashAssets {
@@ -10,7 +10,6 @@ export declare class SplashStateMachine {
10
10
  playing(presentationId: string): StateMachineSnapshot;
11
11
  settlePlayback(presentationId: string, outcome: PlaybackOutcome, reason?: string): StateMachineSnapshot;
12
12
  requestHide(presentationId: string): StateMachineSnapshot;
13
- recovery(presentationId: string): StateMachineSnapshot;
14
13
  hidden(presentationId: string): StateMachineSnapshot;
15
14
  getPlaybackResult(presentationId: string): PlaybackResult | undefined;
16
15
  current(): StateMachineSnapshot;
@@ -45,12 +45,6 @@ export class SplashStateMachine {
45
45
  this.snapshot.phase = 'hiding';
46
46
  return this.current();
47
47
  }
48
- recovery(presentationId) {
49
- this.requireCurrent(presentationId);
50
- if (!this.snapshot.appReady)
51
- this.snapshot.phase = 'recovery';
52
- return this.current();
53
- }
54
48
  hidden(presentationId) {
55
49
  this.requireCurrent(presentationId);
56
50
  this.snapshot = {
package/dist/esm/web.d.ts CHANGED
@@ -6,7 +6,6 @@ export declare class LottieSplashWeb extends WebPlugin implements LottieSplashPl
6
6
  private resolvePlayback?;
7
7
  private overlay?;
8
8
  private progressTimer?;
9
- private recoveryTimer?;
10
9
  show(options: SplashShowOptions): Promise<Presentation>;
11
10
  setLaunchTheme(_options: SplashLaunchThemeOptions): Promise<void>;
12
11
  waitForCompletion(options: {
@@ -21,7 +20,6 @@ export declare class LottieSplashWeb extends WebPlugin implements LottieSplashPl
21
20
  private playComposition;
22
21
  private settle;
23
22
  private showLoadingRail;
24
- private showRecovery;
25
23
  private removeOverlay;
26
24
  private ensureCurrent;
27
25
  private emitState;
package/dist/esm/web.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
2
  import { SplashStateMachine } from './state-machine';
3
- const RECOVERY_TIMEOUT_MS = 15_000;
4
3
  const PROGRESS_DELAY_MS = 1_000;
5
4
  export class LottieSplashWeb extends WebPlugin {
6
5
  stateMachine = new SplashStateMachine();
@@ -8,7 +7,6 @@ export class LottieSplashWeb extends WebPlugin {
8
7
  resolvePlayback;
9
8
  overlay;
10
9
  progressTimer;
11
- recoveryTimer;
12
10
  async show(options) {
13
11
  const state = this.stateMachine.current();
14
12
  if (state.visible && state.presentationId)
@@ -104,7 +102,6 @@ export class LottieSplashWeb extends WebPlugin {
104
102
  this.emitState();
105
103
  if (!state.appReady) {
106
104
  this.progressTimer = window.setTimeout(() => this.showLoadingRail(presentationId), PROGRESS_DELAY_MS);
107
- this.recoveryTimer = window.setTimeout(() => this.showRecovery(presentationId), RECOVERY_TIMEOUT_MS);
108
105
  }
109
106
  }
110
107
  catch {
@@ -127,31 +124,8 @@ export class LottieSplashWeb extends WebPlugin {
127
124
  rail.append(segment);
128
125
  this.overlay?.append(style, rail);
129
126
  }
130
- showRecovery(presentationId) {
131
- let state;
132
- try {
133
- state = this.stateMachine.recovery(presentationId);
134
- }
135
- catch {
136
- return;
137
- }
138
- if (state.presentationId !== presentationId || state.appReady)
139
- return;
140
- this.overlay?.querySelector('[data-splash-loading-rail]')?.remove();
141
- const recovery = document.createElement('div');
142
- recovery.style.cssText = 'position:absolute;bottom:12%;display:grid;gap:12px;place-items:center;color:inherit;font:500 16px system-ui;';
143
- recovery.textContent = 'Still starting…';
144
- const retry = document.createElement('button');
145
- retry.type = 'button';
146
- retry.textContent = 'Try again';
147
- retry.onclick = () => window.location.reload();
148
- recovery.append(retry);
149
- this.overlay?.append(recovery);
150
- this.emitState();
151
- }
152
127
  removeOverlay(presentationId) {
153
128
  window.clearTimeout(this.progressTimer);
154
- window.clearTimeout(this.recoveryTimer);
155
129
  this.overlay?.remove();
156
130
  this.overlay = undefined;
157
131
  this.stateMachine.hidden(presentationId);
@@ -53,12 +53,6 @@ class SplashStateMachine {
53
53
  this.snapshot.phase = 'hiding';
54
54
  return this.current();
55
55
  }
56
- recovery(presentationId) {
57
- this.requireCurrent(presentationId);
58
- if (!this.snapshot.appReady)
59
- this.snapshot.phase = 'recovery';
60
- return this.current();
61
- }
62
56
  hidden(presentationId) {
63
57
  this.requireCurrent(presentationId);
64
58
  this.snapshot = {
@@ -85,7 +79,6 @@ class SplashStateMachine {
85
79
  }
86
80
  }
87
81
 
88
- const RECOVERY_TIMEOUT_MS = 15_000;
89
82
  const PROGRESS_DELAY_MS = 1_000;
90
83
  class LottieSplashWeb extends core.WebPlugin {
91
84
  stateMachine = new SplashStateMachine();
@@ -93,7 +86,6 @@ class LottieSplashWeb extends core.WebPlugin {
93
86
  resolvePlayback;
94
87
  overlay;
95
88
  progressTimer;
96
- recoveryTimer;
97
89
  async show(options) {
98
90
  const state = this.stateMachine.current();
99
91
  if (state.visible && state.presentationId)
@@ -189,7 +181,6 @@ class LottieSplashWeb extends core.WebPlugin {
189
181
  this.emitState();
190
182
  if (!state.appReady) {
191
183
  this.progressTimer = window.setTimeout(() => this.showLoadingRail(presentationId), PROGRESS_DELAY_MS);
192
- this.recoveryTimer = window.setTimeout(() => this.showRecovery(presentationId), RECOVERY_TIMEOUT_MS);
193
184
  }
194
185
  }
195
186
  catch {
@@ -212,31 +203,8 @@ class LottieSplashWeb extends core.WebPlugin {
212
203
  rail.append(segment);
213
204
  this.overlay?.append(style, rail);
214
205
  }
215
- showRecovery(presentationId) {
216
- let state;
217
- try {
218
- state = this.stateMachine.recovery(presentationId);
219
- }
220
- catch {
221
- return;
222
- }
223
- if (state.presentationId !== presentationId || state.appReady)
224
- return;
225
- this.overlay?.querySelector('[data-splash-loading-rail]')?.remove();
226
- const recovery = document.createElement('div');
227
- recovery.style.cssText = 'position:absolute;bottom:12%;display:grid;gap:12px;place-items:center;color:inherit;font:500 16px system-ui;';
228
- recovery.textContent = 'Still starting…';
229
- const retry = document.createElement('button');
230
- retry.type = 'button';
231
- retry.textContent = 'Try again';
232
- retry.onclick = () => window.location.reload();
233
- recovery.append(retry);
234
- this.overlay?.append(recovery);
235
- this.emitState();
236
- }
237
206
  removeOverlay(presentationId) {
238
207
  window.clearTimeout(this.progressTimer);
239
- window.clearTimeout(this.recoveryTimer);
240
208
  this.overlay?.remove();
241
209
  this.overlay = undefined;
242
210
  this.stateMachine.hidden(presentationId);
package/dist/plugin.js CHANGED
@@ -67,12 +67,6 @@ var capacitorLottieSplash = (function (exports, core) {
67
67
  this.snapshot.phase = 'hiding';
68
68
  return this.current();
69
69
  }
70
- recovery(presentationId) {
71
- this.requireCurrent(presentationId);
72
- if (!this.snapshot.appReady)
73
- this.snapshot.phase = 'recovery';
74
- return this.current();
75
- }
76
70
  hidden(presentationId) {
77
71
  this.requireCurrent(presentationId);
78
72
  this.snapshot = {
@@ -99,7 +93,6 @@ var capacitorLottieSplash = (function (exports, core) {
99
93
  }
100
94
  }
101
95
 
102
- const RECOVERY_TIMEOUT_MS = 15_000;
103
96
  const PROGRESS_DELAY_MS = 1_000;
104
97
  class LottieSplashWeb extends core.WebPlugin {
105
98
  stateMachine = new SplashStateMachine();
@@ -107,7 +100,6 @@ var capacitorLottieSplash = (function (exports, core) {
107
100
  resolvePlayback;
108
101
  overlay;
109
102
  progressTimer;
110
- recoveryTimer;
111
103
  async show(options) {
112
104
  const state = this.stateMachine.current();
113
105
  if (state.visible && state.presentationId)
@@ -203,7 +195,6 @@ var capacitorLottieSplash = (function (exports, core) {
203
195
  this.emitState();
204
196
  if (!state.appReady) {
205
197
  this.progressTimer = window.setTimeout(() => this.showLoadingRail(presentationId), PROGRESS_DELAY_MS);
206
- this.recoveryTimer = window.setTimeout(() => this.showRecovery(presentationId), RECOVERY_TIMEOUT_MS);
207
198
  }
208
199
  }
209
200
  catch {
@@ -226,31 +217,8 @@ var capacitorLottieSplash = (function (exports, core) {
226
217
  rail.append(segment);
227
218
  this.overlay?.append(style, rail);
228
219
  }
229
- showRecovery(presentationId) {
230
- let state;
231
- try {
232
- state = this.stateMachine.recovery(presentationId);
233
- }
234
- catch {
235
- return;
236
- }
237
- if (state.presentationId !== presentationId || state.appReady)
238
- return;
239
- this.overlay?.querySelector('[data-splash-loading-rail]')?.remove();
240
- const recovery = document.createElement('div');
241
- recovery.style.cssText = 'position:absolute;bottom:12%;display:grid;gap:12px;place-items:center;color:inherit;font:500 16px system-ui;';
242
- recovery.textContent = 'Still starting…';
243
- const retry = document.createElement('button');
244
- retry.type = 'button';
245
- retry.textContent = 'Try again';
246
- retry.onclick = () => window.location.reload();
247
- recovery.append(retry);
248
- this.overlay?.append(recovery);
249
- this.emitState();
250
- }
251
220
  removeOverlay(presentationId) {
252
221
  window.clearTimeout(this.progressTimer);
253
- window.clearTimeout(this.recoveryTimer);
254
222
  this.overlay?.remove();
255
223
  this.overlay = undefined;
256
224
  this.stateMachine.hidden(presentationId);
@@ -149,7 +149,7 @@ public struct LottieSplashConfiguration {
149
149
  }
150
150
 
151
151
  public enum LottieSplashPhase: String {
152
- case preparing, playing, holding, hiding, hidden, recovery
152
+ case preparing, playing, holding, hiding, hidden
153
153
  }
154
154
 
155
155
  public final class LottieSplashCoordinator {
@@ -159,7 +159,6 @@ public final class LottieSplashCoordinator {
159
159
  /// permanently obscure that bundle during an over-the-air/native rollout mismatch.
160
160
  private let webAdoptionGracePeriod: TimeInterval = 10
161
161
  private let progressDelay: TimeInterval = 1
162
- private let recoveryDelay: TimeInterval = 15
163
162
 
164
163
  public private(set) var presentationId: String?
165
164
  public private(set) var phase: LottieSplashPhase = .hidden
@@ -167,20 +166,17 @@ public final class LottieSplashCoordinator {
167
166
  public private(set) var appReady = false
168
167
  public private(set) var theme: LottieSplashTheme = .dark
169
168
  public var onStateChange: ((LottieSplashCoordinator) -> Void)?
170
- public var onRecoveryRequested: (() -> Void)?
171
169
 
172
170
  private weak var hostController: UIViewController?
173
171
  private var cover: LottieSplashCoverView?
174
172
  private var animationWebView: WKWebView?
175
173
  private var animationMessageBridge: LottieSplashMessageBridge?
176
174
  private var loadingRail: LottieSplashLoadingRail?
177
- private var recoveryWorkItem: DispatchWorkItem?
178
175
  private var progressWorkItem: DispatchWorkItem?
179
176
  private var adoptionWorkItem: DispatchWorkItem?
180
177
  private var adoptedByWeb = false
181
178
  private var webRendererLoaded = false
182
179
  private var progressRemaining = TimeInterval(1)
183
- private var recoveryRemaining = TimeInterval(15)
184
180
  private var waitingClockStartedAt: Date?
185
181
  private var playbackCompletion: ((String, String?) -> Void)?
186
182
  private let queue = DispatchQueue.main
@@ -401,20 +397,13 @@ public final class LottieSplashCoordinator {
401
397
  ])
402
398
  self.loadingRail = rail
403
399
  }
404
- let recovery = DispatchWorkItem { [weak self] in
405
- self?.recoveryRemaining = 0
406
- self?.showRecovery(for: id)
407
- }
408
400
  progressWorkItem = progress
409
- recoveryWorkItem = recovery
410
401
  if self.loadingRail == nil { queue.asyncAfter(deadline: .now() + progressRemaining, execute: progress) }
411
- queue.asyncAfter(deadline: .now() + recoveryRemaining, execute: recovery)
412
402
  }
413
403
 
414
404
  private func resetWaitingIndicators(for id: String) {
415
405
  cancelWaitingTasks()
416
406
  progressRemaining = progressDelay
417
- recoveryRemaining = recoveryDelay
418
407
  scheduleWaitingIndicators(for: id)
419
408
  }
420
409
 
@@ -422,15 +411,12 @@ public final class LottieSplashCoordinator {
422
411
  guard let waitingClockStartedAt else { return }
423
412
  let elapsed = Date().timeIntervalSince(waitingClockStartedAt)
424
413
  progressRemaining = max(0, progressRemaining - elapsed)
425
- recoveryRemaining = max(0, recoveryRemaining - elapsed)
426
414
  cancelWaitingTasks()
427
415
  }
428
416
 
429
417
  private func cancelWaitingTasks() {
430
418
  progressWorkItem?.cancel()
431
- recoveryWorkItem?.cancel()
432
419
  progressWorkItem = nil
433
- recoveryWorkItem = nil
434
420
  waitingClockStartedAt = nil
435
421
  }
436
422
 
@@ -445,33 +431,6 @@ public final class LottieSplashCoordinator {
445
431
  queue.asyncAfter(deadline: .now() + webAdoptionGracePeriod, execute: fallback)
446
432
  }
447
433
 
448
- private func showRecovery(for id: String) {
449
- guard presentationId == id, !appReady else { return }
450
- cancelWaitingTasks()
451
- phase = .recovery
452
- loadingRail?.removeFromSuperview()
453
- loadingRail = nil
454
- let stack = UIStackView()
455
- stack.axis = .vertical
456
- stack.spacing = 12
457
- stack.alignment = .center
458
- stack.translatesAutoresizingMaskIntoConstraints = false
459
- let label = UILabel()
460
- label.text = "Still starting…"
461
- label.accessibilityTraits = .updatesFrequently
462
- let retry = UIButton(type: .system)
463
- retry.setTitle("Try again", for: .normal)
464
- retry.addAction(UIAction { [weak self] _ in self?.onRecoveryRequested?() }, for: .primaryActionTriggered)
465
- stack.addArrangedSubview(label)
466
- stack.addArrangedSubview(retry)
467
- cover?.addSubview(stack)
468
- if let cover {
469
- NSLayoutConstraint.activate([stack.centerXAnchor.constraint(equalTo: cover.centerXAnchor), stack.bottomAnchor.constraint(equalTo: cover.safeAreaLayoutGuide.bottomAnchor, constant: -48)])
470
- }
471
- UIAccessibility.post(notification: .announcement, argument: "Still starting")
472
- emitState()
473
- }
474
-
475
434
  private func dismiss(completion: @escaping (Error?) -> Void) {
476
435
  guard phase != .hidden, let cover, let id = presentationId else { completion(nil); return }
477
436
  phase = .hiding
@@ -17,7 +17,6 @@ public class LottieSplashPlugin: CAPPlugin, CAPBridgedPlugin {
17
17
 
18
18
  override public func load() {
19
19
  coordinator.onStateChange = { [weak self] coordinator in self?.notifyListeners("stateChange", data: self?.stateData(coordinator) ?? [:]) }
20
- coordinator.onRecoveryRequested = { [weak self] in self?.bridge?.webView?.reload() }
21
20
  }
22
21
 
23
22
  @objc public func show(_ call: CAPPluginCall) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-lottie-splash",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Native-first Lottie splash presentation for Capacitor 8",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",