Pular para o conteúdo

Calendário e agendamento

O Control Center se conecta ao Google Calendar para que o seu dia fique ao lado da sua frota. Ele sincroniza os seus eventos, os mostra nas visualizações de mês, semana, dia e agenda, avisa você antes do início de uma reunião e transforma qualquer evento em uma reunião gravada e resumida.

Quase nada. A integração puxa os eventos e os renderiza. Ela não cria, edita nem exclui nada, e não responde a convites. Toda conexão por código de dispositivo, integrada ou própria, solicita calendar.readonly e mais openid email.

Os eventos são sincronizados no banco de dados do próprio espaço de trabalho no servidor (<dataDir>/<workspaceId>/workspace.db) e renderizados por todos os clientes via RPC. Nenhum cliente guarda credencial do Google.

As contas de calendário pertencem ao espaço de trabalho, como tudo o mais no Control Center. Cada espaço de trabalho conecta a própria conta do Google (ou várias), e os eventos e tokens de um espaço de trabalho nunca são visíveis de outro. Trocar de espaço de trabalho troca os calendários que você vê.

Um espaço de trabalho pode conectar várias contas do Google, como uma conta de trabalho e uma pessoal, e os eventos delas são mesclados nas mesmas visualizações.

O cc_server headless não tem navegador para capturar um redirecionamento do OAuth. Por isso ele não usa um: ele autoriza com a concessão de código de dispositivo (RFC 8628). O servidor mostra um código de usuário curto e uma URL do Google, você aprova em qualquer dispositivo que tenha navegador e o servidor consulta até que você aprove. Uma instalação headless consegue conectar uma conta justamente porque não há endpoint de redirecionamento para hospedar.

A consequência que você precisa saber antes de usar as suas próprias credenciais: o tipo de cliente precisa ser “TV and Limited Input devices” do Google. O Google só concede a esse tipo de cliente um conjunto de escopos da lista de permissões, e um projeto em que o Calendar não é permitido para ele falha com invalid_scope — nesse caso você precisaria de um cliente loopback ou web.

Os tokens nunca saem do servidor. Eles são gravados no secrets.json do servidor, no diretório de dados dele, com a chave google_google:<workspaceId>:<email>, junto dos bancos de dados e sob a mesma fronteira de confiança do sistema de arquivos do host. O servidor renova o acesso automaticamente e, quando o Google invalida uma conta em definitivo (uma sessão revogada ou expirada há muito tempo), publica CalendarAuthExpired e exibe um banner de Reconectar em vez de falhar em silêncio.

Uma compilação a partir do código-fonte não inclui nenhuma credencial do Google — você fornece o seu próprio ID de cliente e segredo. As compilações oficiais de lançamento embutem um cliente de código de dispositivo não confidencial para que o fluxo de conexão funcione de imediato; o servidor guarda apenas um marcador que faz referência a ele, nunca uma cópia. GOOGLE_OAUTH_CLIENT_ID (e o respectivo segredo) no ambiente sempre tem precedência sobre o par embutido. Não existe de propósito nenhuma flag --google-client-id: flags desconhecidas são ignoradas, e um segredo em uma linha de comando é legível via ps.

Para usar o seu próprio projeto do Google, consulte Conectar um Google Calendar.

O servidor busca uma janela móvel dos eventos de cada conta conectada — todos os calendários da conta, não apenas o principal — a cada dois minutos, além de sob demanda (inicialização, conexão e atualização manual). O intervalo curto é viável porque a varredura é incremental: cada calendário tem o próprio token de sincronização, então um calendário inalterado custa uma resposta quase vazia em vez de buscar de novo uma janela de cinco meses.

Eventos recorrentes são expandidos no servidor, então nenhum cliente precisa interpretar uma regra de recorrência. Navegar até um mês fora da janela atual carrega esse intervalo sob demanda. Eventos excluídos ou movidos para fora do intervalo são reconciliados na próxima sincronização.

Visualização O que mostra
Mês Uma grade de um mês inteiro (com o pacote kalender)
Semana Os eventos com horário de uma semana em uma grade de horários
Dia Os eventos com horário de um único dia em uma grade de horários
Agenda Uma lista rolável dos próximos eventos

Abra o calendário em /calendar; selecionar um evento abre os detalhes dele em /calendar/:eventId. A visualização que você escolhe fica nas preferências do próprio cliente, então ela não acompanha você em outro dispositivo.

Um agendador que roda a cada minuto procura eventos que começam dentro de uma janela de antecedência configurável e dispara uma notificação “Reunião prestes a começar” (um MeetingStartingSoon, evento de domínio). A notificação traz a URL de entrada quando ela existe, e clicar nela abre os detalhes do evento. Os alertas são deduplicados com base no alertedAt do evento, então a mesma reunião nunca alerta duas vezes, mesmo entre reinicializações, e um evento cujo início passou enquanto o app estava fechado nunca é repetido.

É fácil esbarrar em dois limites. O agendador roda no lado do cliente, no desktop, e apenas para o espaço de trabalho que você tem aberto no momento — um espaço de trabalho em que você não está não dispara alerta algum. E a compilação web não tem pipeline de notificações do sistema operacional nenhum, então ela também não dispara.

A partir de um evento do calendário, você pode iniciar uma gravação de reunião já preenchida com o título do evento. O Control Center guarda um vínculo um para um entre a gravação e o evento, então as notas da reunião e o item do calendário permanecem conectados sem que um recurso dependa do outro.

Gravar e vincular só existe no desktop. No cliente web, a ação informa que a gravação não está disponível — mesmo que o próprio fluxo de gravação da tela de reuniões funcione no navegador.