Textus
You hold the pen. AI keeps your ink flowing. Textus is a free, open-source, next-generation Markdown editor for macOS, Windows and Linux, with a writing assistant built in.
Create and manage reminders on an iPhone
AI summary · website content
ProductivitySwift · PythonGitHub @leonardoramirezrOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗App de recordatorios para iOS hecha con SwiftUI que usa AlarmKit para que cada recordatorio suene como una alarma (aunque el teléfono esté en silencio o en un modo de concentración). No usa dependencias externas: sólo frameworks de Apple (SwiftUI, AlarmKit, AppIntents, Observation) y, para crear recordatorios con la voz o con fotos, la API de Groq.
LeoneraReminders.xcodeproj, elige tu equipo en Signing & Capabilities y ejecuta en un dispositivo.
La primera vez la app pide permiso para programar alarmas (NSAlarmKitUsageDescription está en Config/Info.plist).leonera://voice-recording link
(see LeoneraReminders/Core/DeepLink.swift).
The «Abrir Leonera» widget shows the same logo without the microphone and opens the app on the reminder list,
closing any screen presented on top of it, through the leonera://home link.whisper-large-v3-turbo por defecto), el de texto a recordatorios
(openai/gpt-oss-120b) y el de fotos (qwen/qwen3.8-27b, que acepta imágenes), y el idioma del dictado.
Groq cambia sus modelos seguido, así que Actualizar lista de modelos trae los de la cuenta y también se puede
escribir cualquier id. El modelo responde en JSON ({"reminders":[{"title","due","repeat"}]}) con la fecha de hoy
y los próximos 14 días ya calculados en las instrucciones; la app lo lee de forma tolerante y lo convierte en
recordatorios con la misma regla de repetición que usa el resto de la app.LeoneraReminders/Sounds, sintetizados para el proyecto)."Recordatorio","Fecha límite","Repetir" de Due.
Muestra una vista previa con avisos, omite duplicados y puede pasar los repetitivos vencidos a su próxima fecha.
También acepta encabezados en inglés, punto y coma como separador y archivos en UTF-8, UTF-16 o Windows-1252."Completado" con la fecha en que se completó, para que los completados no vuelvan como pendientes.
Va en UTF-8 con BOM para abrirse bien en Excel o Numbers.Alarm.Schedule.fixed) en AlarmKit. Las repeticiones
las calcula la app: al completar, el recordatorio avanza a la siguiente ocurrencia y se programa una alarma nueva.
(Las repeticiones nativas de AlarmKit sólo cubren "semanal a tal hora".)LiveActivityIntents (SnoozeReminderIntent, SnoozeOptionsIntent) dentro del proceso de la app, que actualiza el recordatorio y reprograma.AlarmSyncService compara los recordatorios con AlarmManager.alarms y cancela/programa lo necesario; también
reprograma si cambian los botones o el tiempo de posponer. Si AlarmKit llega a su límite de alarmas, se programan
primero las más cercanas.CalendarEventSource reads EventKit,
CalendarEventAlarmPlanner in Core/ computes the first alarm of each event). Its UUID is derived from the event
occurrence, the lead time and the alarm settings, so an existing alarm is kept as is and a moved, renamed or deleted
event gets its old alarm cancelled. The repeats after each stop are kept in CalendarEventRings (Core/, saved in
UserDefaults): one current alarm per unacknowledged event, with a random UUID, and the stop button
(CalendarEventRingStopIntent), the Abrir app button (CalendarEventOpenAppIntent) or a cleared notification
plans the next one.LeoneraReminders/
App/ Punto de entrada
Core/ Modelo y lógica sin interfaz (repeticiones, CSV, matriz, configuración, instrucciones y lectura de
las respuestas de Groq) — probado con `swift test`
Alarms/ AlarmKit: sincronización, metadatos e intents de los botones
Assistant/ Groq (peticiones), clave en el llavero, grabación del dictado y fotos
Stores/ Persistencia (JSON en Application Support y UserDefaults)
Views/ SwiftUI (Views/Assistant: barra para crear, voz, fotos, revisión y configuración del asistente)
LeoneraWidgets/ Lock screen widgets (WidgetKit extension) that open the app on voice capture or on its home screen
Config/Info.plist
Tests/ReminderCoreTests/
scripts/ Builds firmados: API de App Store Connect (asc.py) y GitHub Pages (publish-pages.sh, pages.py)
La lógica de LeoneraReminders/Core también es un paquete de Swift (Package.swift) que compila en macOS y Linux:
swift test
.github/workflows/build.yml se ejecuta en cada push (a cualquier rama salvo gh-pages) y a mano desde
Actions › Build IPA › Run workflow. Compila, firma Ad Hoc y publica el .ipa en un release y en GitHub Pages,
con una página desde la que se instala tocando un botón en Safari.
| Rama | Tag | Release |
|---|---|---|
main | 0.x.0 (empieza en 0.1.0; cada push sube el número del medio) | Estable, marcada como Latest |
| cualquier otra | build-<N>-<commit> (N = número de ejecución del workflow, commit = 7 caracteres del hash) | Pre-release, nunca Latest |
Ningún build se cancela: los de main van en fila (para no repetir versión) y los de otras ramas corren en paralelo.
En Settings › Secrets and variables › Actions › Repository secrets (secrets del repositorio, no de una organización):
| Secret | Qué es |
|---|---|
ASC_KEY_ID | Key ID de la clave de API de App Store Connect |
ASC_ISSUER_ID | Issuer ID (aparece arriba de la lista de claves) |
ASC_KEY_P8 | Contenido completo del archivo AuthKey_XXXX.p8 (con las líneas BEGIN/END) |
APPLE_TEAM_ID | Team ID de la cuenta de Apple Developer (10 caracteres) |
La clave debe ser una Team Key (App Store Connect › Users and Access › Integrations › App Store Connect API) con rol Admin: Xcode la usa para registrar el App ID, crear los perfiles y firmar con el certificado de distribución gestionado en la nube.
.ipa sin firmar (sólo va al release; hay que firmarlo con Sideloadly, AltStore
o un certificado propio).scripts/asc.py check comprueba con la API de App Store Connect que la clave funciona y que hay al menos un
dispositivo iOS registrado.xcodebuild archive con firma automática (-allowProvisioningUpdates y la clave de API). El bundle ID es
com.<owner>.<repo> en minúsculas (aquí com.leonardoramirezr.leonerareminders) o el valor de la variable de
repositorio APP_BUNDLE_ID si existe; se pasa a xcodebuild como build setting APP_BUNDLE_ID, y el proyecto
usa $(APP_BUNDLE_ID) (una extensión usaría $(APP_BUNDLE_ID).<sufijo>). La app no usa App Groups ni otras
capacidades que haya que activar a mano en el portal.xcodebuild -exportArchive con method=release-testing (Ad Hoc): el perfil incluye todos los dispositivos
registrados. Se verifica que cada bundle lleve un perfil Ad Hoc y se muestra cuántos dispositivos incluye.scripts/publish-pages.sh) y se agrega el enlace de instalación al resumen de la
ejecución y a las notas del release.xcodebuild crea en cada ejecución.Después del primer build firmado (que crea la rama gh-pages), ve a Settings › Pages y en
Build and deployment elige Deploy from a branch, rama gh-pages y carpeta / (root).
La página queda en https://leonardoramirezr.github.io/LeoneraReminders/: la portada lista todos los builds y tiene
un botón para instalar la última versión estable; cada build tiene su carpeta (/<tag>/) con el .ipa, el
manifest.plist y su propio botón de instalación. La rama gh-pages se reescribe en cada publicación como un único
commit (los .ipa no se acumulan en el historial) y guarda todas las versiones de main y los últimos 50 builds de
otras ramas.
Basta con registrar su UDID en Certificates, Identifiers & Profiles › Devices y hacer push (o lanzar el workflow a mano): el siguiente build regenera el perfil Ad Hoc con todos los dispositivos registrados. Los builds anteriores sólo se instalan en los dispositivos que ya estaban registrados cuando se hicieron.