Tudo é projetado e projetado seguindo meu gosto e visão. Este é um projeto paralelo pessoal para eu aprender sobre o Mastodon e experimentar novas ideias de UI/UX.
Características
? Várias contas
? Compor janela pop-out/in
? Tema claro/escuro/automático
? Notificações agrupadas
? Tópico de comentários aninhados
? Recuperação de rascunho não enviado
? Aumenta o Carrossel™️
⚡ Shortcuts™️ com modos de visualização como multicolunas ou barra de guias
#️⃣ Linha do tempo com várias hashtags
Decisões de projeto
As ações de status (resposta, promoção, favorito, favorito, etc.) ficam ocultas por padrão . Eles aparecem apenas na página de status individual. Isso é para reduzir a desordem e a distração. Isso pode resultar em menor engajamento, mas não estamos perseguindo números aqui.
Boost é representado pelo ícone de foguete . O ícone de seta dupla verde (retuíte para Twitter) não parece adequado para o termo “impulso”. Foguete verde parece estranho, então uso roxo.
Nomes de usuário curtos ( @username ) são exibidos em linhas do tempo, em vez do nome de usuário completo da conta ( @username@instance ) . Apesar da diretriz mencionar que “A descentralização deve ser transparente para o usuário”, não acho que devamos passar isso na cara todas as vezes. Existem também algumas preocupações de acessibilidade relacionadas ao leitor de tela com o nome de usuário completo, embora este aplicativo da web infelizmente ainda não esteja acessível.
Não há reprodução automática para vídeo/GIF/qualquer coisa na linha do tempo . A linha do tempo já está uma grande bagunça com muitas pessoas, marcas, notícias e mídia tentando chamar sua atenção. Não vamos piorar as coisas. (A exceção atual agora seriam os emojis animados.)
URLs baseados em hash . Este aplicativo da web não pretende ser um substituto completo do front-end existente do Mastodon. Não há SEO, banco de dados, servidor sem servidor ou qualquer servidor de longa duração. Eu posso estar errado um dia.
Implementações sutis de UI
Exibição do nome de usuário
Na linha do tempo, o nome do usuário é exibido como [NAME] @[username] .
Para @[username] , sempre exclua o nome de domínio da instância.
Se [NAME]for igual a @[username] , então @[username] também será excluído.
Aumenta o carrossel
A partir das postagens buscadas (por exemplo, 20 postagens por busca), se o número de impulsos for superior a um quarto do total de postagens ou mais de 3 impulsos consecutivos, a interface do carrossel de impulsos será acionada.
Se o número de boosts for superior a 3 quartos do total de postagens, a interface do carrossel de boosts será colocada no final do total de postagens buscadas (por "página").
Caso contrário, a IU do carrossel de reforços será colocada entre as postagens.
Emblema do número da linha (por exemplo, linha 1/X)
Verifique cada postagem em busca de inReplyToId no cache ou em solicitações de API adicionais, até que a postagem raiz seja encontrada.
Se a postagem raiz for encontrada, o emblema mostrará o número de índice da postagem no tópico.
Limite até 3 solicitações de API, pois a postagem raiz pode ser muito antiga ou o thread é muito longo.
Se o número do índice não puder ser encontrado, o emblema retornará para mostrar Thread sem o número.
Recheio de hashtag em colapso
O primeiro parágrafo do conteúdo da postagem com mais de 3 hashtags será reduzido para no máximo 3 linhas.
Os parágrafos subsequentes após o primeiro parágrafo com mais de 3 hashtags serão reduzidos para 1 linha.
Parágrafos adjacentes com mais de 1 hashtag após os parágrafos recolhidos serão recolhidos para 1 linha.
Se houver texto ao redor ou entre as hashtags, elas não serão recolhidas.
As hashtags recolhidas serão anexadas com ... no final.
Eles também estão ligeiramente desbotados para reduzir o ruído visual.
Abrir a visualização da postagem revelará as hashtags não recolhidas.
Postagens filtradas
As postagens filtradas por "Ocultar completamente" ficarão ocultas, sem interface de usuário para revelá-las.
As postagens filtradas por "Ocultar com um aviso" serão parcialmente ocultadas, mostrando o nome do filtro e o nome do autor.
O conteúdo pode ser parcialmente revelado passando o mouse sobre a postagem, com a dica mostrando o texto da postagem.
Clicar nele abrirá a página Postagem.
Manter pressionado ou clicar com o botão direito irá "espiar" a postagem com uma interface de usuário na página inferior.
No carrossel de boosts, eles são classificados até o final do carrossel.
Desenvolvimento
Pré-requisitos: Node.js 18+
npm install – Instalar dependências
npm run dev - Inicia o servidor de desenvolvimento e messages:extract ( clean + ``watch`) em paralelo
npm run build – Compilação para produção
npm run preview – Visualize a compilação de produção
npm run fetch-instances - Busque a lista de instâncias em joinmastodon.org/servers, salve-a em src/data/instances.json
npm run sourcemap - Execute source-map-explorer na compilação de produção
npm run messages:extract - Extrai mensagens de arquivos de origem e atualiza os catálogos de mensagens de localidade
Pilha de tecnologia
Vite - ferramenta de construção
Preact - biblioteca de UI
Valtio - Gestão do Estado
Roteador React - Roteamento
masto.js - cliente API Mastodon
Iconify - Biblioteca de ícones
Ícones MingCute
Lingui - Internacionalização
Vanilla CSS - Sim, sou da velha escola.
Algumas delas podem mudar no futuro. O mundo front-end está em constante mudança.
Internacionalização
Todas as traduções estão disponíveis como arquivos gettext .po na pasta src/locales . O idioma padrão é o inglês ( en ). Regras plurais CLDR são usadas para pluralização. Idiomas RTL (da direita para a esquerda) também são suportados com direção de texto, renderização de ícones e layout adequados.
No carregamento da página, o idioma padrão é detectado por meio destes métodos, na ordem (a primeira correspondência é usada):
Parâmetro de URL lang/?lang=zh-Hant
lang da chave localStorage
navigator.language do navegador
Os usuários podem alterar o idioma nas configurações, que definem a chave localStoragelang .
Guia para tradutores
*Inspirado no Manual do Translate WordPress:
Não traduza literalmente, traduza organicamente.
Tente manter o mesmo nível de formalidade (ou informalidade)
Não use gírias ou termos específicos do público
Esteja atento aos espaços reservados para variáveis. Muitas strings possuem espaços reservados, por exemplo, {account} (variável), <0>{name}0> (tag com variável) e # (espaço reservado para número).
As reticências (…) são intencionais. Não remova isso.
Nielsen Norman Group: "Incluir reticências no texto do comando para indicar quando mais informações são necessárias"
Diretrizes de interface humana da Apple: "Anexar reticências ao rótulo de um item de menu quando a ação exigir mais informações antes de ser concluída. O caractere de reticências (…) sinaliza que as pessoas precisam inserir informações ou fazer escolhas adicionais, normalmente em outra visualização."
Desenvolvimento de aplicativos do Windows: "Elipses significam incompletude."
Carimbos de data e hora, intervalos de datas, números, nomes de idiomas e segmentação de texto são tratados pela API de internacionalização ECMAScript.
Intl.DateTimeFormat - por exemplo, "8 de agosto", "08/08/2024"
Intl.RelativeTimeFormat - por exemplo, "2 dias atrás", "em 2 dias"
Intl.NumberFormat - por exemplo, "1.000", "10K"
Intl.DisplayNames - por exemplo, "English" ( en ) em chinês tradicional ( zh-Hant ) é "英文"
Intl.Locale (com polyfill para navegadores mais antigos)
Intl.Segmenter (com polyfill para navegadores mais antigos)
Notas técnicas
IDs para strings são gerados automaticamente em vez de definidos explicitamente. Alguns dos benefícios são evitar o problema de “nomear coisas” e evitar duplicatas.
IDs explícitas poderão ser introduzidas no futuro, quando os requisitos e as prioridades mudarem. A biblioteca (Lingui) permite ambos.
Por favor, relate problemas se determinadas strings forem traduzidas de forma diferente com base no contexto, cultura ou região.
Não há strings para notificações push. O idioma é definido no servidor da instância.
Os seletores de data HTML nativos, por exemplo sempre seguirão a localidade do sistema e não a localidade definida pelo usuário.
"ALT" no emblema ALT não é traduzido. Ele serve como um padrão reconhecível em todos os idiomas.
Os nomes de emojis personalizados não são localizados, portanto, as pesquisas não funcionam para idiomas diferentes do inglês.
A API GIPHY oferece suporte a uma lista de idiomas para pesquisas.
A marca Unicode da direita para a esquerda (RLM) ( U+200F , ) pode precisar ser usada para texto misto RTL/LTR, especialmente para o elemento ( document.title ).
No desenvolvimento, há um código de idioma pseudo-LOCALE adicional, usado para pseudolocalização. É para teste e não aparecerá na produção.
Ao compilar para produção, as mensagens do catálogo em inglês ( en ) não são agrupadas separadamente. Outras localidades são agrupadas como arquivos separados e carregadas sob demanda. Isso garante que en esteja sempre disponível como substituto.
Traduções voluntárias
As traduções são gerenciadas no Crowdin. Você pode ajudar oferecendo traduções voluntárias.
Leia a documentação de introdução para começar.
Auto-hospedagem
Este é um aplicativo da web estático puro . Você pode hospedá-lo onde quiser.
Duas maneiras (escolha uma):
Maneira fácil
Vá para Releases e baixe o phanpy-dist.zip ou phanpy-dist.tar.gz mais recente. É pré-construído, portanto não é necessário executar nenhum comando de instalação/construção. Extraia-o. Sirva a pasta de arquivos extraídos.
Maneira de construção personalizada
Requer Node.js.
Baixe ou git clone este repositório. Use o ramo production para versões estáveis , main para as versões mais recentes . Construa-o executando npm run build (após npm install ). Sirva a pasta dist .
A personalização pode ser feita passando variáveis de ambiente para o comando build. Exemplos:
PHANPY_CLIENT_NAME= " Phanpy Dev "
PHANPY_WEBSITE= " https://dev.phanpy.social "
npm run build
PHANPY_DEFAULT_INSTANCE=hachyderm.io
PHANPY_DEFAULT_INSTANCE_REGISTRATION_URL=https://hachyderm.io/auth/sign_up
PHANPY_PRIVACY_POLICY_URL=https://hachyderm.io/privacy-policy
npm run build
Título da página da Web, mostrado na janela do navegador ou no título da guia
Título do aplicativo, quando instalado como PWA, mostrado na tela inicial, dock do macOS, barra de tarefas do Windows, etc.
Título do cartão OpenGraph, quando compartilhado em redes sociais
Nome do cliente, ao registrar o aplicativo para autenticação e mostrado como cliente usado em postagens em alguns aplicativos/clientes
PHANPY_WEBSITE (opcional, mas recomendado, padrão: https://phanpy.social ) afeta:
URL canônica do site
URL do cartão OpenGraph, quando compartilhado em redes sociais
Caminho raiz para a imagem do cartão OpenGraph
URL do cliente, ao registrar o aplicativo para autenticação e mostrado como cliente usado em postagens em alguns aplicativos/clientes
PHANPY_DEFAULT_INSTANCE (opcional, sem padrões):
por exemplo, 'mastodon.social', sem https://
Instância padrão para login
Ao efetuar login, o usuário será redirecionado instantaneamente para a página de autenticação da instância, em vez de precisar digitar manualmente a URL da instância e enviar
PHANPY_DEFAULT_INSTANCE_REGISTRATION_URL (opcional, sem padrões):
URL da página de registro da instância
Por exemplo, https://mastodon.social/auth/sign_up
PHANPY_PRIVACY_POLICY_URL (opcional, padrão para a política de privacidade da instância oficial):
URL da página da política de privacidade
Pode especificar a política de privacidade da própria instância
PHANPY_DEFAULT_LANG (opcional):
O idioma padrão é inglês ( en ), se não for especificado.
Linguagem substituta após vários métodos de detecção (parâmetro de consulta lang , chave lang em localStorage e navigator.language )
PHANPY_LINGVA_INSTANCES (opcional, lista separada por espaço, padrão: lingva.phanpy.social [...hard-coded list of fallback instances] ):
Especifique uma lista de instâncias separadas por espaço. Primeiro será usado como padrão antes de voltar para as instâncias subsequentes. Se houver apenas 1 instância, significa que não há substituto.
Pode especificar uma instância auto-hospedada do Lingva, alimentada por lingva-translate ou lingva-api
Lista de instâncias substitutas codificadas em /.env
↗️ Lista de instâncias do lingva-translate
PHANPY_IMG_ALT_API_URL (opcional, sem padrões):
Terminal de API para instância auto-hospedada de img-alt-api.
Se fornecido, uma configuração aparecerá para os usuários ativarem o gerador de descrição de imagem no compositor. Desativado por padrão.
PHANPY_GIPHY_API_KEY (opcional, sem padrões):
Chave de API para GIPHY. Consulte a documentação da API.
Se fornecido, uma configuração aparecerá para os usuários ativarem o seletor de GIF no compositor. Desativado por padrão.
Isso não é auto-hospedado.
Hospedagem de site estático
Experimente a pesquisa on-line sobre "como hospedar sites estáticos", pois há muitas maneiras de fazer isso.
Hospedagem Lingva-translate ou lingva-api
Consulte a documentação para lingva-translate ou lingva-api.
Implantações comunitárias
Eles são auto-hospedados por outras pessoas maravilhosas.
ferengi.one por @david@weaknotes.com
halo.mookiesplace.com por @mookie@mookiesplace.com
phanpy.bauxite.tech por @b4ux1t3@hachyderm.io
phanpy.blaede.family por @cassidy@blaede.family
phanpy.crmbl.uk por @snail@crmbl.uk
phanpy.cz por @zdendys@mamutovo.cz
phanpy.fulda.social por @Ganneff@fulda.social
phanpy.gotosocial.social por @admin@gotosocial.social
phanpy.hear-me.social por @admin@hear-me.social
phanpy.mastodon.world por @ruud@mastodon.world
phanpy.mstdn.mx por @maop@mstdn.mx
phanpy.social.tchncs.de por @milan@social.tchncs.de
phanpy.tilde.zone por @ben@tilde.zone
phanpy.vmst.io por @vmstan@vmst.io
social.qrk.one por @kev@fosstodon.org
Observação: adicione o seu criando uma solicitação pull.
Custos
Custos envolvidos na execução e desenvolvimento deste aplicativo web:
Nome de domínio (.social): US$ 23,18/ano (US$ 6,87 1º ano)
Sou um dos primeiros usuários do Twitter. O Twitter foi lançado em 15 de julho de 2006. Entrei em dezembro de 2006 e meu primeiro tweet foi postado em 18 de dezembro de 2006.
Eu sei como o Twitter parece antigo. Foi divertido.
Naquela época, fiz um clone do Twitter chamado "Twig", escrito em Python e Google App Engine. Quase criei meu próprio cliente de desktop do Twitter escrito em Appcelerator Titanium. Dei uma das minhas melhores palestras sobre o cliente Twitter em uma miniconferência. Eu construí uma coisa chamada "Twitter Columns", um aplicativo da web que mostra sua lista de seguidores, os seguidores de seus seguidores, seus seguidores, os seguidores de seus seguidores e assim por diante. Em 2009, escrevi uma postagem no blog intitulada “Como comecei com o Twitter”. Criei dois temas para o DestroyTwitter (um cliente desktop feito com Adobe Air por Jonnie Hallman) e um deles se chama "Vimeo". Em 2013, escrevi meu próprio site de backup de tweets com um front-end para visualizar meus tweets e um backend CouchDB para armazená-los.
Já se passaram mais de 15 anos .
E aqui estou. Construindo um cliente web Mastodon.
Clientes web alternativos
Garfos Fanpy ↓
Ágora
Avental (aposentado) - garfos ↓
Semáforo
antes
Cuco+
Sengi
Saboneteira
Alce - garfos ↓
elk.fedified.com
Mastodeque
Troncos
Deutinho
Caixa de areia
Statuzer
Presa
Mastodon Glitch Edition (front-end independente)
Mangano
A mesa
Mais...
?♂️ Aviso a todos os outros desenvolvedores de clientes de mídia social
Por favor, copie as ideias e experimentos da interface do usuário deste aplicativo. Acho que alguns deles são muito bons e seria ótimo se mais aplicativos os tivessem.
Se você não é um desenvolvedor, informe seus desenvolvedores de clientes de mídia social favoritos sobre este aplicativo e peça-lhes que copiem as ideias e experimentos da interface do usuário.