9dfa06ffee
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Signed-off-by: cls_宁波本机 <908705107@qq.com>
92 lines
2.7 KiB
Dart
92 lines
2.7 KiB
Dart
/// Reminder time presets shared by the "Remind me later" sheet.
|
|
///
|
|
/// Mirrors `desktop/src/features/reminders/lib/timePresets.ts` — same labels,
|
|
/// same "always strictly in the future" guarantee.
|
|
library;
|
|
|
|
class ReminderTimePreset {
|
|
final ReminderTimePresetId id;
|
|
final String label;
|
|
final int Function() getTimestamp;
|
|
|
|
const ReminderTimePreset({
|
|
this.id = ReminderTimePresetId.legacy,
|
|
required this.label,
|
|
required this.getTimestamp,
|
|
});
|
|
}
|
|
|
|
/// Stable identifiers let the sheet localize labels without putting UI
|
|
/// strings into the reminder scheduling model.
|
|
enum ReminderTimePresetId {
|
|
legacy,
|
|
in30Minutes,
|
|
in1Hour,
|
|
in3Hours,
|
|
tomorrow9am,
|
|
nextMonday9am,
|
|
}
|
|
|
|
int _nowSeconds() => DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
|
|
|
/// Next occurrence of [dayOffset] days from now at 9am local time. If that
|
|
/// instant is already past, roll to the following day so the result is
|
|
/// always in the future.
|
|
int nextDayAt9am(int dayOffset, {DateTime? now}) {
|
|
final current = now ?? DateTime.now();
|
|
var target = DateTime(
|
|
current.year,
|
|
current.month,
|
|
current.day + dayOffset,
|
|
9,
|
|
);
|
|
if (!target.isAfter(current)) {
|
|
target = DateTime(target.year, target.month, target.day + 1, 9);
|
|
}
|
|
return target.millisecondsSinceEpoch ~/ 1000;
|
|
}
|
|
|
|
/// Days until next Monday (1-7), matching the desktop preset semantics.
|
|
int daysUntilNextMonday(DateTime now) {
|
|
final days = (DateTime.monday - now.weekday) % 7;
|
|
return days == 0 ? 7 : days;
|
|
}
|
|
|
|
final List<ReminderTimePreset> reminderTimePresets = [
|
|
ReminderTimePreset(
|
|
id: ReminderTimePresetId.in30Minutes,
|
|
label: 'In 30 minutes',
|
|
getTimestamp: () => _nowSeconds() + 30 * 60,
|
|
),
|
|
ReminderTimePreset(
|
|
id: ReminderTimePresetId.in1Hour,
|
|
label: 'In 1 hour',
|
|
getTimestamp: () => _nowSeconds() + 60 * 60,
|
|
),
|
|
ReminderTimePreset(
|
|
id: ReminderTimePresetId.in3Hours,
|
|
label: 'In 3 hours',
|
|
getTimestamp: () => _nowSeconds() + 3 * 60 * 60,
|
|
),
|
|
ReminderTimePreset(
|
|
id: ReminderTimePresetId.tomorrow9am,
|
|
label: 'Tomorrow at 9am',
|
|
getTimestamp: () => nextDayAt9am(1),
|
|
),
|
|
ReminderTimePreset(
|
|
id: ReminderTimePresetId.nextMonday9am,
|
|
label: 'Next Monday at 9am',
|
|
getTimestamp: () => nextDayAt9am(daysUntilNextMonday(DateTime.now())),
|
|
),
|
|
];
|
|
|
|
/// Combine a picked date and time into a future Unix timestamp (seconds), or
|
|
/// null when the instant is not strictly in the future — the shared guard for
|
|
/// the custom picker so a past time never fires immediately.
|
|
int? combineCustomDateTime(DateTime date, int hour, int minute) {
|
|
final target = DateTime(date.year, date.month, date.day, hour, minute);
|
|
final timestamp = target.millisecondsSinceEpoch ~/ 1000;
|
|
if (timestamp <= _nowSeconds()) return null;
|
|
return timestamp;
|
|
}
|