diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..6691e2948 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,44 @@ +{ + "name": "Nicolium", + "dockerComposeFile": "docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspaces/nicolium", + + "features": { + "ghcr.io/devcontainers/features/node:1": { + "version": "20", + "nodeGypDependencies": true + } + }, + + "remoteUser": "vscode", + "updateRemoteUserUID": true, + + "forwardPorts": [7312], + "portsAttributes": { + "7312": { + "label": "Nicolium", + "onAutoForward": "openBrowser" + } + }, + + "postCreateCommand": "bash .devcontainer/post-create.sh", + + "customizations": { + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "oxc.oxc-vscode", + "stylelint.vscode-stylelint", + "wix.vscode-import-cost" + ] + } + }, + + "containerEnv": { + "WAYLAND_DISPLAY": "" + }, + "remoteEnv": { + "WAYLAND_DISPLAY": "" + } +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 000000000..8a436c934 --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,10 @@ +version: "3.8" + +services: + app: + image: mcr.microsoft.com/devcontainers/base:ubuntu + command: sleep infinity + volumes: + - ..:/workspaces/nicolium:Z + ports: + - "127.0.0.1:7312:7312" diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh new file mode 100644 index 000000000..62b7774dc --- /dev/null +++ b/.devcontainer/post-create.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail + +corepack enable +mkdir -p ~/.local/bin + +platform="$(uname -s)-$(uname -m)" +formatjs_url="" + +case "$platform" in + Linux-x86_64) + formatjs_url="https://github.com/formatjs/formatjs/releases/download/formatjs_cli_v1.1.0/formatjs_cli-linux-x64" + ;; + Darwin-arm64) + formatjs_url="https://github.com/formatjs/formatjs/releases/download/formatjs_cli_v1.1.0/formatjs_cli-darwin-arm64" + ;; +esac + +if [[ -n "$formatjs_url" ]]; then + curl -fsSL "$formatjs_url" -o ~/.local/bin/formatjs + chmod +x ~/.local/bin/formatjs +fi + +pnpm install --ignore-scripts diff --git a/.gitignore b/.gitignore index 70f70853a..3abc1cbb8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +node_modules /node_modules/ yarn-error.log* coverage/ package-lock.json +.pnpm-store diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 31aa3bd64..f0a0e412a 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,8 @@ { "recommendations": [ "dbaeumer.vscode-eslint", + "ms-vscode-remote.remote-containers", + "oxc.oxc-vscode", "stylelint.vscode-stylelint", "wix.vscode-import-cost" ] diff --git a/packages/nicolium/src/columns/timeline.tsx b/packages/nicolium/src/columns/timeline.tsx index e99a84c40..65b8d232d 100644 --- a/packages/nicolium/src/columns/timeline.tsx +++ b/packages/nicolium/src/columns/timeline.tsx @@ -209,10 +209,16 @@ const TimelineGap: React.FC = ({ gap, onFillGap, firstEntry }) => interface ITimelineStatusInfo { status: SelectedStatus; rebloggedBy: Array; + reblogVisibility?: string; timelineId: string; } -const TimelineStatusInfo: React.FC = ({ status, rebloggedBy, timelineId }) => { +const TimelineStatusInfo: React.FC = ({ + status, + rebloggedBy, + reblogVisibility, + timelineId, +}) => { const features = useFeatures(); const isReblogged = rebloggedBy.length > 0; @@ -256,19 +262,19 @@ const TimelineStatusInfo: React.FC = ({ status, rebloggedBy avatarSize={42} icon={} text={ - // status.visibility === 'private' ? ( - // - // ) : ( - - // ) + reblogVisibility === 'private' ? ( + + ) : ( + + ) } /> ); @@ -281,6 +287,7 @@ const TimelineStatusInfo: React.FC = ({ status, rebloggedBy interface ITimelineStatus { id: string; rebloggedBy: Array; + reblogVisibility?: string; timelineId: string; contextType?: FilterContextType; isConnectedTop?: boolean; @@ -341,6 +348,7 @@ const TimelineStatus: React.FC = (props): React.JSX.Element => )} @@ -440,6 +448,7 @@ const Timeline: React.FC = ({ onMoveUp={() => handleMoveUp(index)} onMoveDown={() => handleMoveDown(index)} rebloggedBy={entry.rebloggedBy} + reblogVisibility={entry.reblogVisibility} timelineId={timelineId} // showGroup={showGroup} /> diff --git a/packages/nicolium/src/components/accounts/profile-stats.tsx b/packages/nicolium/src/components/accounts/profile-stats.tsx index 6fbd8695c..d524fb55a 100644 --- a/packages/nicolium/src/components/accounts/profile-stats.tsx +++ b/packages/nicolium/src/components/accounts/profile-stats.tsx @@ -2,7 +2,6 @@ import { Link } from '@tanstack/react-router'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; -import Text from '@/components/ui/text'; import { useSettings } from '@/stores/settings'; import { shortNumberFormat } from '@/utils/numbers'; @@ -44,18 +43,11 @@ const ProfileStats: React.FC = ({ account, onClickHandler }) => { } return ( -
+
{!demetricator && ( -
- - {shortNumberFormat(account.statuses_count)} - - - - +
+ {shortNumberFormat(account.statuses_count)} +
)} @@ -63,44 +55,22 @@ const ProfileStats: React.FC = ({ account, onClickHandler }) => { to='/@{$username}/followers' params={{ username: account.acct }} onClick={onClickHandler} - title={intl.formatNumber(account.followers_count)} - className='hover:underline' + title={intl.formatMessage(messages.followersCount, { count: account.followers_count })} > -
- {!demetricator && ( - - {shortNumberFormat(account.followers_count)} - - )} - - - -
+ {!demetricator && {shortNumberFormat(account.followers_count)}} + + -
- {!demetricator && ( - - {shortNumberFormat(account.following_count)} - - )} - - - -
+ {!demetricator && {shortNumberFormat(account.following_count)}} + + {account.subscribers_count > 0 && ( @@ -108,24 +78,13 @@ const ProfileStats: React.FC = ({ account, onClickHandler }) => { to='/@{$username}/subscribers' params={{ username: account.acct }} onClick={onClickHandler} - title={intl.formatNumber(account.subscribers_count)} - className='hover:underline' + title={intl.formatMessage(messages.subscribersCount, { + count: account.subscribers_count, + })} > -
- {!demetricator && ( - - {shortNumberFormat(account.subscribers_count)} - - )} - - - -
+ {!demetricator && {shortNumberFormat(account.subscribers_count)}} + + )}
diff --git a/packages/nicolium/src/components/navigation/sidebar-navigation-link.tsx b/packages/nicolium/src/components/navigation/sidebar-navigation-link.tsx index 4b3a1d4c8..46f95a7e0 100644 --- a/packages/nicolium/src/components/navigation/sidebar-navigation-link.tsx +++ b/packages/nicolium/src/components/navigation/sidebar-navigation-link.tsx @@ -30,7 +30,7 @@ const SidebarNavigationLink: React.FC = React.memo( const LinkComponent = (to === undefined ? 'button' : Link) as typeof Link; - const isActive = matchRoute({ to }) !== false; + const isActive = matchRoute({ to, ...rest }) !== false; const handleClick: React.EventHandler = (e) => { if (onClick) { @@ -43,7 +43,7 @@ const SidebarNavigationLink: React.FC = React.memo( return (
  • = ({ showGroup={showGroup} variant='slim' fromBookmarks={other.scrollKey === 'bookmarked_statuses'} - fromHomeTimeline={timelineId === 'home'} /> ); diff --git a/packages/nicolium/src/components/statuses/status.tsx b/packages/nicolium/src/components/statuses/status.tsx index d469d7676..f5430e276 100644 --- a/packages/nicolium/src/components/statuses/status.tsx +++ b/packages/nicolium/src/components/statuses/status.tsx @@ -15,7 +15,6 @@ import Text from '@/components/ui/text'; import Emojify from '@/features/emoji/emojify'; import StatusTypeIcon from '@/features/status/components/status-type-icon'; import { Hotkeys } from '@/features/ui/components/hotkeys'; -import { useFeatures } from '@/hooks/use-features'; import { useGroupQuery } from '@/queries/groups/use-group'; import { useFollowedTags } from '@/queries/hashtags/use-followed-tags'; import { useStatus, type SelectedStatus } from '@/queries/statuses/use-status'; @@ -175,7 +174,6 @@ interface IStatus { showGroup?: boolean; showInfo?: boolean; fromBookmarks?: boolean; - fromHomeTimeline?: boolean; className?: string; } @@ -196,7 +194,6 @@ const Status: React.FC = React.memo((props) => { showGroup = true, showInfo = true, fromBookmarks = false, - fromHomeTimeline = false, className, contextType, } = props; @@ -204,7 +201,6 @@ const Status: React.FC = React.memo((props) => { const intl = useIntl(); const navigate = useNavigate(); const router = useRouter(); - const features = useFeatures(); const { toggleStatusesMediaHidden, unfilterStatus } = useStatusMetaActions(); const { deleted, showFiltered } = useStatusMeta(status.id); @@ -479,12 +475,6 @@ const Status: React.FC = React.memo((props) => { } /> ); - } else if (fromHomeTimeline) { - return ( - features.followHashtags && ( - - ) - ); } }, [status.account, group?.id]); diff --git a/packages/nicolium/src/features/compose-event/tabs/edit-event.tsx b/packages/nicolium/src/features/compose-event/tabs/edit-event.tsx index 81ca828f0..6fc9b6c45 100644 --- a/packages/nicolium/src/features/compose-event/tabs/edit-event.tsx +++ b/packages/nicolium/src/features/compose-event/tabs/edit-event.tsx @@ -309,6 +309,7 @@ const EditEvent: React.FC = ({ statusId }) => { = ({ }) => (
    = ({ const intl = useIntl(); return ( -
    -