Skip to content

Countdown Timer starts counting upward on end #20

Description

@AlanChauchet

Library Version

1.0.0

React Native Version

0.81.5

React Version

19.1.0

Expo Version

54.0.9

Minimal Reproduction

  1. Steps to reproduce

Running this hook when a timer is active :

import { useEffect, useMemo, useRef } from "react";
import { type LiveActivityVariants, Voltra } from "voltra";
import {
  startLiveActivity,
  stopLiveActivity,
  updateLiveActivity,
} from "voltra/client";
import type { IActiveTimer } from "@/types/timer";
import { i18n } from "@/utils/translations";

export function useCurrentTimerLiveActivity(timerEndsAt: number) {
  const timerEndsAtMs = timerEndsAt * 1000;

  const variants = useMemo<LiveActivityVariants>(
    () => ({
      lockScreen: {
        activityBackgroundTint: background,
        content: (
          <Voltra.HStack
            alignment="center"
            spacing={16}
            style={{
              paddingHorizontal: 16,
              paddingVertical: 8,
            }}
          >
            <Voltra.Symbol
              name="bell.fill"
              scale="large"
              tintColor={accent}
              type="hierarchical"
            />
            <Voltra.VStack alignment="leading">
              <Voltra.Text
                numberOfLines={1}
                style={{
                  color: foreground,
                  fontSize: 18,
                  fontWeight: "600" as const,
                }}
              >
                Rest timer
              </Voltra.Text>
            </Voltra.VStack>
            <Voltra.Spacer style={{ flex: 1 }} />
            <Voltra.HStack
              style={{
                width: 80,
              }}
            >
              <Voltra.Spacer style={{ flex: 1 }} />
              <Voltra.Timer
                autoHideOnEnd
                direction="down"
                endAtMs={timerEndsAtMs}
                style={{
                  fontSize: 18,
                  fontWeight: "600",
                  color: muted,
                }}
                textStyle="timer"
              />
            </Voltra.HStack>
          </Voltra.HStack>
        ),
      },
    }),
    [timerEndsAtMs]
  );

  const activityId = useRef<string | null>(null);

  useEffect(() => {
    const start = async () => {
      if (activityId.current) {
        await updateLiveActivity(activityId.current, variants, {
          relevanceScore: 1.0,
          staleDate: timerEndsAtMs,
          dismissalPolicy: "immediate",
        });
      } else {
        const newActivityId = await startLiveActivity(variants, {
          activityName: "current-timer",
          relevanceScore: 1.0,
          staleDate: timerEndsAtMs,
          dismissalPolicy: "immediate",
        });
        activityId.current = newActivityId;
      }
    };

    if (timerEndsAtMs > 0) {
      start();
    } else if (activityId.current) {
      stopLiveActivity(activityId.current);
      activityId.current = null;
    }
  }, [variants, timerEndsAtMs]);

  useEffect(() => {
    return () => {
      if (activityId.current) {
        stopLiveActivity(activityId.current);
        activityId.current = null;
      }
    };
  }, []);
}
  1. Expected behavior

When timerEndsAt is reached, timer is expected to hide (because of autoHideOnEnd) or at least stay at "00:00"

  1. Actual Behavior

Timer goes from "00:30" to "00:00" as expected and then stays displayed and starts counting up

Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-01-16.at.15.41.07.mov

Additional Information (Optional)

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions