Arquitetura¶
O DroidDeck é um monorepo com duas metades que evoluem juntas:
DroidDeck/
DroidDeck/ C# backend (.NET 8): WinForms tray + ASP.NET Core + SignalR. Serves the API and the web app.
app/ Flutter app: the phone runtime and the web configurator (same code).
tests/ Backend tests.
scripts/ Utilities (deploying the web build to wwwroot).
website/ This documentation and the project's landing page.
Backend (DroidDeck/)¶
- Host:
Program.cssobe o ASP.NET Core em0.0.0.0:4787e o ícone da bandeja (frmPrincipal.cs), a menos que receba--headless. Os serviços são registrados por área emServiceRegistration.cs(AddDeckCore,AddActionProviders,AddIntegrations). - Auth:
Auth/— autenticação por chave de API (header, bearer ouaccess_tokenna query), com comparação em tempo constante. A chave é gerada em%LocalAppData%\DroidDeck\apikey. - Ações:
Actions/—IActionProvidere o schema;Actions/Providers/tem os tipos embutidos (atalho, mídia, mixer, multiação, timer, Windows, HTTP, Steam…). - Integrações:
Integrations/<Nome>/— uma pasta por integração, com o serviço, o provedor de ação e, quando tem, o controlador e o serviço de reconexão (Discord,Obs,Tuya,Soundboard,HomeAssistant,Spotify,Twitch,YouTube). Todas implementamIIntegration(listadas emGET /api/integrations); as que usam conta herdam deAccountIntegration(configuração cifrada, OAuth e uma tela de configuração única no app). - Controladores:
Controllers/— endpoints REST do deck, áudio, mídia, biblioteca, informação e macro. - Hub:
Hubs/DeckHub.cs— hub SignalR em/deckHub; envia o estado aos clientes. - Serviços:
Services/— o deck em si:ActionExecutorService(despacho por tipo),ActionPolicy(ações privilegiadas),StreamDeckConfigService(perfis),ButtonToggleService(dois estados),InfoService(botões de informação),TimerService,ForegroundWatcher,BackupService,SystemMonitorServicee os serviços de áudio e mídia. - Idioma:
Lib/Localization*.cs—L.T("…")responde em inglês quando o pedido pede. - Descoberta:
Lib/DiscoveryServer.cs— responde no UDP 7573. - Web estático: o build web do Flutter é servido de
wwwroot/.
App (app/)¶
Uma única base de código Flutter, com dois papéis:
- No navegador (servido pelo PC), abre o configurador: perfis, grade com arrastar e soltar, painel de propriedades.
- No celular, é o runtime: a grade de botões (dimensionada para a tela), a aba Áudio e as configurações de pareamento e integrações.
Pontos principais:
Lugares principais:
lib/core/droiddeck_client/— modelos da API (DeckButton, perfis…).lib/core/i18n/—tr("…")e os dicionários de inglês (en/*.dart).lib/src/stream_deck/buttons/— como cada tipo de ação desenha o botão (renderers.dartliga o tipo ao desenhista;button_look.darttem o botão comum, o visual de dois estados e os ícones).lib/src/stream_deck/widgets/— grade, botões de informação e o editor do botão (editor/tem as seções dele).lib/src/stream_deck/actions/— seletor de ação, formulário do schema e editores próprios.lib/src/services/signalr_service.dart— conexão com o hub, com reconexão sem fim.lib/src/connection/— chaves de conexão e a lista de PCs pareados.lib/src/config/— telas de configuração (pareamento, aparência, integrações).
Contrato¶
O app e o backend compartilham:
- REST em
/api/...— veja API; - SignalR em
/deckHub— eventos do servidor para o cliente; - Descoberta UDP na porta 7573;
- URI de pareamento
droiddeck://pair?ip=&port=&key=.
Adicionando um novo tipo de ação¶
Cada tipo de ação é um IActionProvider (DroidDeck/Actions/). Ele executa a ação e descreve
seus campos num ActionSchema; o editor do app monta o formulário a partir de
GET /api/actions/schema, então um tipo simples não precisa de nenhum código em Flutter:
- Implemente
IActionProvideremDroidDeck/Actions/Providers/(Type,Describe(),ExecuteAsync()). Os campos são texto, texto longo, número, liga/desliga ou seleção; uma seleção pode carregar as opções de um endpoint (OptionsSource, com{campo}substituído) e qualquer campo pode depender de outro (When). - Registre em
ServiceRegistration.AddActionProviders(services.AddSingleton<IActionProvider, MeuProvider>()). - Se tiver estado ao vivo, implemente
IStatefulActionProvider(StateEvent,GetState()): oDeckHubenvia ao conectar e o app passa a ouvir. - Só se precisar: um desenhista em
app/lib/src/stream_deck/buttons/(estado ao vivo no botão), uma tela própria emapp/lib/src/stream_deck/actions/editors/(Editor = "nome") ou uma página de configuração. - Se executar código ou acessar a rede a partir do PC, inclua o tipo entre os privilegiados do
ActionPolicy.