팬피
최소한의 독선적인 Mastodon 웹 클라이언트.
?️ 발음 : /fænpi/
( FAN-pee
) ? 듣다
이것은 Mastodon의 대체 웹 클라이언트입니다.
- ? 제작 : https://phanpy.social
-
production
지점 - 덜 자주 휴식
- 중요하지 않은 한 느린 수정
- ?️ 개발 : https://dev.phanpy.social
-
main
- 새로운 멋진 콘텐츠를 더 빨리 볼 수 있습니다
- 더 자주 깨질 수 있습니다
- 훨씬 빨리 고쳐질 수도 있습니다
? 업데이트를 보려면 Mastodon에서 @phanpy를 팔로우하세요 ✨
모든 것이 내 취향과 비전에 따라 설계되고 제작되었습니다. 이것은 Mastodon에 대해 배우고 새로운 UI/UX 아이디어를 실험하기 위한 개인적인 사이드 프로젝트입니다.
특징
- ? 여러 계정
- ? 작성 창 팝업/인
- ? 밝음/어두움/자동 테마
- ? 그룹화된 알림
- ? 중첩된 댓글 스레드
- ? 보내지 않은 초안 복구
- ? Carousel™️을 향상시킵니다.
- ⚡ 다중 열 또는 탭 표시줄과 같은 보기 모드를 갖춘 바로가기™️
- #️⃣ 다중 해시태그 타임라인
디자인 결정
- 상태 작업(답장, 홍보, 즐겨찾기, 북마크 등)은 기본적으로 숨겨져 있습니다 .
개별 상태 페이지에만 표시됩니다. 이는 혼란과 산만함을 줄이기 위한 것입니다. 참여도가 낮아질 수 있지만 여기서는 숫자를 쫓지 않습니다. - 부스트는 로켓 아이콘으로 표시됩니다 .
녹색 이중 화살표 아이콘(Twitter의 경우 리트윗)은 "부스트"라는 용어에 적합하지 않은 것 같습니다. 녹색 로켓이 이상해 보여서 보라색을 사용했습니다. - 전체 계정 사용자 이름(
@username@instance
) 대신 짧은 사용자 이름( @username
)이 타임라인에 표시됩니다 .
"분권화는 사용자에게 투명해야 한다"는 지침에도 불구하고 매번 이를 표면화할 필요는 없다고 생각합니다. 전체 사용자 이름에는 스크린 리더 관련 접근성 문제도 있지만 안타깝게도 이 웹 앱에는 아직 액세스할 수 없습니다. - 타임라인의 비디오/GIF/무엇이든 자동 재생되지 않습니다 .
타임라인은 이미 많은 사람, 브랜드, 뉴스, 미디어가 여러분의 관심을 끌기 위해 애쓰는 거대한 혼란 상태입니다. 상황을 악화시키지 말자. (현재 예외는 애니메이션 이모티콘입니다.) - 해시 기반 URL .
이 웹 앱은 Mastodon의 기존 프런트 엔드를 완전히 대체하기 위한 것이 아닙니다. SEO, 데이터베이스, 서버리스 또는 장기 실행 서버가 없습니다. 언젠가는 틀릴 수도 있어요.
미묘한 UI 구현
사용자 이름 표시
- 타임라인에는 사용자 이름이
[NAME] @[username]
으로 표시됩니다. -
@[username]
의 경우 항상 인스턴스 도메인 이름을 제외하세요. -
[NAME]
이 @[username]
과 동일해 보이는 경우 @[username]
도 제외됩니다.
캐러셀 부스트
- 가져온 게시물(예: 가져오기당 게시물 20개)에서 부스트 수가 총 게시물의 4분의 1을 초과하거나 연속 부스트가 3개를 초과하는 경우 부스트 캐러셀 UI가 트리거됩니다.
- 부스트 수가 총 게시물의 3/4을 초과하는 경우 부스트 캐러셀 UI는 가져온 총 게시물 끝에("페이지"당) 배치됩니다.
- 그렇지 않으면 부스트 캐러셀 UI가 게시물 사이에 배치됩니다.
스레드 번호 배지(예: 스레드 1/X)
- 루트 게시물을 찾을 때까지 캐시 또는 추가 API 요청에서
inReplyToId
에 대한 모든 게시물을 확인하세요. - 루트 게시물이 발견되면 배지에 스레드에 있는 게시물의 색인 번호가 표시됩니다.
- 루트 게시물이 매우 오래되었거나 스레드가 너무 길기 때문에 API 요청을 최대 3개로 제한하세요.
- 색인 번호를 찾을 수 없는 경우 배지는 번호 없이
Thread
표시하도록 대체됩니다.
해시태그 스터핑이 무너지고 있습니다.
- 3개 이상의 해시태그가 포함된 게시물 콘텐츠의 첫 번째 단락은 최대 3줄로 축소됩니다.
- 해시태그가 3개 이상인 첫 번째 단락 이후의 후속 단락은 1줄로 축소됩니다.
- 접힌 문단 뒤의 해시태그가 1개 이상인 인접 문단은 1줄로 접혀집니다.
- 해시태그 주변이나 사이에 텍스트가 있으면 접히지 않습니다.
- 접힌 해시태그는 끝에
...
가 추가됩니다. - 또한 시각적 노이즈를 줄이기 위해 약간 페이드 아웃됩니다.
- 게시물 보기를 열면 축소되지 않은 해시태그가 표시됩니다.
필터링된 게시물
- "완전히 숨기기"로 필터링된 게시물은 표시할 수 있는 UI 없이 숨겨집니다.
- "경고와 함께 숨기기"로 필터링된 게시물은 부분적으로 숨겨져 필터 이름과 작성자 이름이 표시됩니다.
- 게시물 위로 마우스를 가져가면 게시물 텍스트를 표시하는 도구 설명을 통해 내용을 부분적으로 볼 수 있습니다.
- 클릭하면 게시물 페이지가 열립니다.
- 길게 누르거나 마우스 오른쪽 버튼을 클릭하면 바텀 시트 UI가 포함된 게시물을 "미리볼" 수 있습니다.
- 부스트 캐러셀에서는 캐러셀 끝에 정렬됩니다.
개발
전제조건: Node.js 18+
-
npm install
- 종속성 설치 -
npm run dev
- 개발 서버 및 messages:extract
( clean
+ ``watch`) 병렬로 -
npm run build
- 프로덕션용 빌드 -
npm run preview
- 프로덕션 빌드 미리보기 -
npm run fetch-instances
- Joinmastodon.org/servers에서 인스턴스 목록을 가져와서 src/data/instances.json
에 저장합니다. -
npm run sourcemap
- 프로덕션 빌드에서 source-map-explorer
실행합니다. -
npm run messages:extract
- 소스 파일에서 메시지를 추출하고 로케일 메시지 카탈로그를 업데이트합니다.
기술 스택
- Vite - 빌드 도구
- Preact - UI 라이브러리
- Valtio - 상태 관리
- 반응 라우터 - 라우팅
- masto.js - 마스토돈 API 클라이언트
- Iconify - 아이콘 라이브러리
- Lingui - 국제화
- 바닐라 CSS - 예, 저는 구식입니다.
이들 중 일부는 향후 변경될 수 있습니다. 프론트엔드 세계는 끊임없이 변화하고 있습니다.
국제화
모든 번역은 src/locales
폴더에 gettext .po
파일로 제공됩니다. 기본 언어는 영어( en
)입니다. CLDR 복수 규칙은 복수화에 사용됩니다. RTL(오른쪽에서 왼쪽) 언어도 적절한 텍스트 방향, 아이콘 렌더링 및 레이아웃으로 지원됩니다.
페이지 로드 시 기본 언어는 다음 방법을 통해 순서대로 감지됩니다(첫 번째 일치 항목이 사용됨).
- URL 매개변수
lang
예: /?lang=zh-Hant
-
localStorage
키 lang
- 브라우저의
navigator.language
사용자는 localStorage
키 lang
을 설정하는 설정에서 언어를 변경할 수 있습니다.
번역가를 위한 가이드
*워드프레스 핸드북 번역에서 영감을 얻었습니다:
- 문자 그대로 번역하지 말고 유기적으로 번역하세요.
- 동일한 수준의 형식(또는 비공식)을 유지하도록 노력하세요.
- 속어나 청중을 특정하는 용어를 사용하지 마세요.
- 변수의 자리 표시자에 주의하세요. 많은 문자열에는
{account}
(변수), <0>{name}0>
(변수가 포함된 태그) 및 #
(숫자 자리 표시자)과 같은 자리 표시자가 있습니다. - 줄임표(…)는 의도적인 것입니다. 제거하지 마십시오.
- Nielsen Norman Group: "추가 정보가 필요한 경우를 나타내기 위해 명령 텍스트에 줄임표를 포함합니다."
- Apple 휴먼 인터페이스 지침: "작업을 완료하기 전에 추가 정보가 필요한 경우 메뉴 항목 레이블에 줄임표를 추가합니다. 줄임표 문자(…)는 일반적으로 다른 보기 내에서 사람들이 정보를 입력하거나 추가 선택을 해야 함을 나타냅니다."
- Windows 앱 개발: "타원은 불완전함을 의미합니다."
- 날짜 타임스탬프, 날짜 범위, 숫자, 언어 이름 및 텍스트 분할은 ECMAScript 국제화 API에 의해 처리됩니다.
-
Intl.DateTimeFormat
- 예: "8월 8일", "2024년 8월 8일" -
Intl.RelativeTimeFormat
- 예: "2일 전", "2일 후" -
Intl.NumberFormat
형식 - 예: "1,000", "10K" -
Intl.DisplayNames
- 예를 들어 중국어 번체( zh-Hant
)의 "English"( en
)는 "英文"입니다. -
Intl.Locale
(이전 브라우저의 경우 폴리필 사용) -
Intl.Segmenter
(이전 브라우저용 폴리필 포함)
기술 노트
자원봉사 번역
번역은 Crowdin에서 관리됩니다. 자원봉사 번역을 통해 도움을 줄 수 있습니다.
시작하려면 소개 문서를 읽어보세요.
자체 호스팅
이것은 순수한 정적 웹 앱 입니다. 원하는 곳 어디에서나 호스팅할 수 있습니다.
두 가지 방법(하나 선택):
쉬운 방법
릴리스로 이동하여 최신 phanpy-dist.zip
또는 phanpy-dist.tar.gz
다운로드하세요. 사전 빌드되었으므로 설치/빌드 명령을 실행할 필요가 없습니다. 그것을 추출하십시오. 추출된 파일의 폴더를 제공합니다.
맞춤형 구축 방식
Node.js가 필요합니다.
이 저장소를 다운로드하거나 git clone
. 안정적인 릴리스에는 production
브랜치를 사용하고, 최신 릴리스에는 main
를 사용하세요. npm run build
실행하여 빌드합니다( npm install
이후). dist
폴더를 제공하십시오.
환경 변수를 빌드 명령에 전달하여 사용자 정의를 수행할 수 있습니다. 예:
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
.env
파일에서 설정할 수도 있습니다.
사용 가능한 변수:
-
PHANPY_CLIENT_NAME
(선택 사항, 기본값: Phanpy
)은 다음에 영향을 미칩니다.- 브라우저 창이나 탭 제목에 표시되는 웹 페이지 제목
- PWA로 설치된 경우 홈 화면, macOS 도크, Windows 작업 표시줄 등에 표시되는 앱 제목
- OpenGraph 카드 제목(소셜 네트워크에서 공유 시)
- 클라이언트 이름, 인증을 위해 앱을 등록할 때 일부 앱/클라이언트의 게시물에 사용되는 클라이언트로 표시됩니다.
-
PHANPY_WEBSITE
(선택 사항이지만 권장됨, 기본값: https://phanpy.social
)은 다음에 영향을 미칩니다.- 웹사이트의 표준 URL
- OpenGraph 카드 URL(소셜 네트워크에서 공유되는 경우)
- OpenGraph 카드 이미지의 루트 경로
- 클라이언트 URL은 인증을 위해 앱을 등록할 때 일부 앱/클라이언트의 게시물에 사용되는 클라이언트로 표시됩니다.
-
PHANPY_DEFAULT_INSTANCE
(선택사항, 기본값 없음):- 예:
https://
없는 'mastodon.social' - 로그인을 위한 기본 인스턴스
- 로그인 시 사용자는 인스턴스 URL을 수동으로 입력하고 제출할 필요 없이 즉시 인스턴스 인증 페이지로 리디렉션됩니다.
-
PHANPY_DEFAULT_INSTANCE_REGISTRATION_URL
(선택사항, 기본값 없음):- 인스턴스 등록 페이지의 URL
- 예:
https://mastodon.social/auth/sign_up
-
PHANPY_PRIVACY_POLICY_URL
(선택사항, 기본값은 공식 인스턴스의 개인정보 보호정책):- 개인정보 보호정책 페이지의 URL
- 인스턴스의 자체 개인 정보 보호 정책을 지정할 수 있습니다.
-
PHANPY_DEFAULT_LANG
(선택사항):- 지정되지 않은 경우 기본 언어는 영어(
en
)입니다. - 여러 감지 방법 이후의 대체 언어(
lang
쿼리 매개변수, localStorage
및 navigator.language
의 lang
키)
-
PHANPY_LINGVA_INSTANCES
(선택 사항, 공백으로 구분된 목록, 기본값: lingva.phanpy.social [...hard-coded list of fallback instances]
):- 공백으로 구분된 인스턴스 목록을 지정합니다. 첫 번째는 후속 인스턴스로 대체되기 전에 기본값으로 사용됩니다. 인스턴스가 1개만 있으면 대체가 없음을 의미합니다.
- lingva-translate 또는 lingva-api로 구동되는 자체 호스팅 Lingva 인스턴스를 지정할 수 있습니다.
-
/.env
에 하드 코딩된 대체 인스턴스 목록 - ↗️ lingva-translate 인스턴스 목록
-
PHANPY_IMG_ALT_API_URL
(선택사항, 기본값 없음):- img-alt-api의 자체 호스팅 인스턴스에 대한 API 엔드포인트입니다.
- 제공된 경우 사용자가 작성기에서 이미지 설명 생성기를 활성화할 수 있는 설정이 나타납니다. 기본적으로 비활성화되어 있습니다.
-
PHANPY_GIPHY_API_KEY
(선택사항, 기본값 없음):- GIPHY용 API 키입니다. API 문서를 참조하세요.
- 제공된 경우 사용자가 작성기에서 GIF 선택기를 활성화할 수 있는 설정이 나타납니다. 기본적으로 비활성화되어 있습니다.
- 이것은 자체 호스팅이 아닙니다.
정적 사이트 호스팅
방법은 다양하므로 "정적 사이트를 자체 호스팅하는 방법"을 온라인으로 검색해 보세요.
Lingva 번역 또는 lingva-api 호스팅
lingva-translate 또는 lingva-api에 대한 설명서를 참조하세요.
커뮤니티 배포
이들은 다른 훌륭한 사람들이 자체 호스팅합니다.
- ferengi.one @david@weaknotes.com 작성
- halo.mookiesplace.com(@mookie@mookiesplace.com 작성)
- @b4ux1t3@hachyderm.io의 phanpy.bauxite.tech
- @cassidy@blaede.family의 phanpy.blaede.family
- @snail@crmbl.uk의 phanpy.crmbl.uk
- @zdendys@mamutovo.cz의 phanpy.cz
- @Ganneff@fulda.social의 phanpy.fulda.social
- @admin@gotosocial.social의 phanpy.gotosocial.social
- @admin@hear-me.social의 phanpy.hear-me.social
- @ruud@mastodon.world의 phanpy.mastodon.world
- @maop@mstdn.mx의 phanpy.mstdn.mx
- @milan@social.tchncs.de의 phanpy.social.tchncs.de
- @ben@tilde.zone의 phanpy.tilde.zone
- @vmstan@vmst.io의 phanpy.vmst.io
- @kev@fosstodon.org의 social.qrk.one
참고: 끌어오기 요청을 생성하여 추가하세요.
소송 비용
이 웹 앱을 실행하고 개발하는 데 드는 비용:
- 도메인 이름(.social): USD$23.18/년 (USD$6.87 1년차)
- 호스팅: 무료
- 개발, 디자인, 유지보수: "무료" (나의 소중한 시간)
마스코트
팬피(Phanpy)는 땅타입 포켓몬입니다.
유지관리자 + 기여자
번역 자원봉사자
- alidsds11(아랍어)
- 대안(한국어)
- BoFFire(아랍어, 프랑스어, Kabyle)
- 브라와루어(러시아어)
- cbasje(네덜란드어)
- cbo92 (프랑스어)
- CDN(중국어 간체)
- dannypsnl(중국어 번체)
- databio(카탈로니아어)
- 디즈로(이탈리아어)
- Drift6944(체코)
- drydenwu(중국어 번체)
- 엘리사크(프랑스어)
- 엘팜플리나(스페인어)
- Fitik(에스페란토, 히브리어)
- 프리지아(일본어)
- 고스어(갈리시아어)
- 홍민희 (한국어)
- 휴고글리프(에스페란토, 스페인어)
- 이사르어(카탈로니아어)
- 칼리우우(폴란드어)
- karlafej(체코)
- katullo11(이탈리아어)
- 키타(독일어)
- 룬(태국어)
- lucasofchirst(옥시탄어, 포르투갈어, 포르투갈어, 브라질어)
- LukeHong(중국어 번체)
- marcin.kozinski(폴란드어)
- mkljczkk(폴란드어)
- 모조소은(한국어)
- 모리얼 (한국어)
- MrWillCom(중국어 간체)
- nclm(프랑스어)
- 파즈피(이탈리아어)
- 펑크록걸(바스크어)
- 라데코스(프랑스어)
- 라젬(체코)
- realpixelcode(독일어)
- 레자호세인자데(페르시아어)
- rwmpelstilzchen(에스페란토, 히브리어)
- SadmL(러시아어)
- SadmL_AI(러시아어)
- 슈지3(일본어)
- Sky_NiniKo(프랑스어)
- Steffo99(이탈리아어)
- Su5hicz(체코)
- tferrermo(스페인어)
- tkbremnes(노르웨이어 복말)
- tux93 (독일어)
- Vac31. (리투아니아 사람)
- 발틀라이(핀란드어)
- 바시리리(폴란드어)
- 항해(중국어 번체)
- xabi_itzultzaile(바스크어)
- xen4n(우크라이나어)
- xqueralt(카탈로니아어)
- 지리수트(Kabyle)
- zkreml(체코)
뒷이야기
나는 트위터의 초기 사용자 중 한 명입니다. 트위터는 2006년 7월 15일에 시작되었습니다. 저는 2006년 12월에 가입했고 2006년 12월 18일에 첫 트윗이 게시되었습니다.
나는 트위터가 얼마나 초기에 생겼는지 압니다. 재미있었습니다.
그 당시 저는 Python과 Google App Engine으로 작성된 "Twig"라는 Twitter 복제본을 만들었습니다. 나는 Appcelerator Titanium으로 작성된 나만의 Twitter 데스크톱 클라이언트를 거의 만들었습니다. 나는 미니 컨퍼런스에서 트위터 클라이언트에 관해 최고의 강연을 했습니다. 저는 팔로어 목록, 팔로어의 팔로어, 팔로어, 팔로어의 팔로어 등을 보여주는 웹 앱인 "Twitter Columns"라는 것을 만들었습니다. 2009년에 나는 "내가 트위터를 시작한 방법"이라는 제목의 블로그 게시물을 썼습니다. 저는 DestroyTwitter(Jonnie Hallman이 Adobe Air로 만든 데스크탑 클라이언트)용으로 두 개의 테마를 만들었고 그 중 하나는 "Vimeo"입니다. 2013년에 나는 내 트윗을 볼 수 있는 프런트 엔드와 이를 저장할 CouchDB 백엔드가 있는 나만의 트윗 백업 사이트를 작성했습니다.
15년이 넘었 습니다.
그리고 여기 있습니다. Mastodon 웹 클라이언트 구축.
대체 웹 클라이언트
- 팬피 포크 ↓
- 피나포레(은퇴) - 포크 ↓
- 뻐꾸기+
- 센기
- 비누 상자
- 엘크 - 포크 ↓
- 마스토덱
- 트렁크스
- 투티
- 쓰레기통
- 스타츄저
- 엄니
- Mastodon Glitch Edition(독립형 프런트엔드)
- 망간
- 더데스크
- 더...
?♂️ 다른 모든 소셜 미디어 클라이언트 개발자에 대한 공지
이 앱의 UI 아이디어와 실험을 복사해 주세요. 나는 그들 중 일부가 꽤 좋다고 생각하고 더 많은 앱이 있다면 좋을 것입니다.
개발자가 아닌 경우 좋아하는 소셜 미디어 클라이언트 개발자에게 이 앱에 대해 알리고 UI 아이디어와 실험을 복사하도록 요청하세요.
특허
MIT.