diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 3a53ec8..cd86f68 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -16,7 +16,8 @@ "Bash(find /var/home/felipecn/DEV/MeowSpool/backend/bruno-routes -name \"*.yml\" ! -name \"route.yml\" -exec sed -i 's|http://0\\\\.0\\\\.0\\\\.0:8080|{{base_url}}|g; s|https://meowspool\\\\.felipecncloud\\\\.com|{{base_url}}|g' {} +)", "Bash(find /var/home/felipecn/DEV/MeowSpool/backend/bruno-routes -name \"*.yml\" ! -name \"route.yml\" ! -name \"Dashboard.yml\" -exec sed -i 's| url: \\\\\\({{.*}}\\\\\\)| url: \"\"\\\\1\"\"|g' {} +)", "Bash(find /var/home/felipecn/DEV/MeowSpool/backend/bruno-routes -name \"*.yml\" ! -name \"route.yml\" -exec sed -i 's| url: \"\"\\\\?\\\\\\(.*\\\\\\)\"\"\\\\?$| url: \"\"\\\\1\"\"|g; s| url: \"\"\\\\\\(.*\\\\\\)\"\"\"\"\\\\?$| url: \"\"\\\\1\"\"|g' {} +)", - "Bash(cargo check:*)" + "Bash(cargo check:*)", + "Bash(ls /var/home/felipecn/DEV/MeowSpool/mobile/app/\\\\\\(auth\\\\\\))" ] } } diff --git a/mobile/agent.md b/mobile/agent.md index 7da5e66..843a805 100644 --- a/mobile/agent.md +++ b/mobile/agent.md @@ -88,6 +88,8 @@ mobile/ │ │ ├── verify-email.tsx ← RU-0 │ │ ├── reset-password.tsx ← 117-0 │ │ └── password-reset-done.tsx ← 135-0 +│ ├── filament/ +│ │ └── [id].tsx ← Deep link handler: redireciona meowspool://filament/{id} → /(app)/inventory/{id} │ └── (app)/ │ ├── _layout.tsx ← Stack autenticado │ ├── (tabs)/ @@ -222,6 +224,7 @@ Arquivo: `src/shared/theme.ts` - Scheme: `meowspool://` - Filamento: `meowspool://filament/` → `/(app)/inventory/` (singular, alinhado com backend) +- O redirecionamento é feito pela rota `app/filament/[id].tsx` com `` do expo-router — garante que o deep link abrido externamente (QR Code, NFC, link compartilhado) sempre chegue na tela correta - O scanner (`scanner.tsx`) faz match via `/meowspool:\/\/filament\/([^/]+)/` e navega para `/(app)/inventory/` - O QR Code de cada filamento exibe `meowspool://filament/` usando `react-native-qrcode-svg` - As tags NFC NTAG215 gravam a mesma URI `meowspool://filament/` como NDEF URI record — mesmo deep link, infraestrutura compartilhada @@ -361,6 +364,24 @@ Base: `EXPO_PUBLIC_API_URL` (padrão: `http://localhost:3000/api/v1`) ## Mudanças Recentes (14/03/2026) +### ✅ Deep Link Handler — `app/filament/[id].tsx` + +Criada rota `app/filament/[id].tsx` para tratar deep links abertos externamente (QR Code, NFC, mensagem compartilhada). Sem essa rota, o expo-router exibia "Unmatched Route" ao abrir `meowspool://filament/{id}` fora do app. + +```tsx +import { Redirect, useLocalSearchParams } from 'expo-router'; + +export default function FilamentDeepLink() { + const { id } = useLocalSearchParams<{ id: string }>(); + return ; +} +``` + +O redirecionamento leva para `/(app)/inventory/[id]` (tela de detalhe), que já lida com usuário não autenticado via o guard do `_layout.tsx` raiz. + +--- + + ### ✅ Suporte a Impressoras Pequenas — Niimbot D11/D110 (`label.tsx`) **Arquivo alterado**: `app/(app)/filaments/[id]/label.tsx` diff --git a/mobile/src/adapters/remote/ApiAuthRepository.ts b/mobile/src/adapters/remote/ApiAuthRepository.ts index f257888..e488840 100644 --- a/mobile/src/adapters/remote/ApiAuthRepository.ts +++ b/mobile/src/adapters/remote/ApiAuthRepository.ts @@ -23,7 +23,7 @@ export class ApiAuthRepository implements AuthRepository { } async refreshToken(refreshToken: string): Promise> { - const { data } = await httpClient.post('/auth/refresh', { refreshToken }); + const { data } = await httpClient.post('/auth/refresh', { refresh_token: refreshToken }); return { accessToken: data.access_token, refreshToken: data.refresh_token, diff --git a/mobile/src/adapters/remote/httpClient.ts b/mobile/src/adapters/remote/httpClient.ts index 129863d..e621ecc 100644 --- a/mobile/src/adapters/remote/httpClient.ts +++ b/mobile/src/adapters/remote/httpClient.ts @@ -63,7 +63,7 @@ httpClient.interceptors.response.use( const refreshToken = await SecureStore.getItemAsync(SECURE_STORE_REFRESH_TOKEN); if (!refreshToken) throw new Error('No refresh token'); - const { data } = await axios.post(`${API_BASE_URL}/auth/refresh`, { refreshToken }); + const { data } = await axios.post(`${API_BASE_URL}/auth/refresh`, { refresh_token: refreshToken }); await SecureStore.setItemAsync(SECURE_STORE_ACCESS_TOKEN, data.access_token); await SecureStore.setItemAsync(SECURE_STORE_REFRESH_TOKEN, data.refresh_token);