[nextjs]SNS Server-51(myapp61) 

👉🏻 myapp61에서는 알림페이지에서 데이터가 중복 표시되는 문제를 수정 합니다.
In myapp61, the issue where data was displayed redundantly on the notification page is being fixed.

👉🏻 타임라인에서 데이터가 없으면 Home,Local,Federated 탭이 사라지는 문제를 수정합니다.
Fixes an issue where the Home, Local, and Federated tabs disappear when there is no data in the timeline.

👉🏻 내가 작성하지 않은 글도 DELETE표시되는 문제를 수정합니다.
Fixes an issue where posts I did not write were marked for deletion.

👉🏻 전체 코드는 깃허브에서 확인 할 수 있습니다.
You can find the full code on GitHub.

https://github.com/gideonslife01/flm-nextjs

📁 전체 프로젝트 구조 / Overall Project Structure

myapp project/  
├── app/  (Next.js App Router)
│   ├── .well-known/webfinger/route.ts  -> webfinger
│   ├── hooks/useCursorPagination.ts    -> Pagination Hook
│   ├── api/follow/route.ts    -> Follow API(temporary)
│   ├── api/announce/route.ts  -> Boost(Announcement)
│   ├── api/like/route.ts.     -> Like API
│   ├── api/posts/route.ts     -> Writing API(deprecated)
│   ├── api/timeline/route.ts  -> Timeline API
│   ├── api/followinglist/route.ts  -> followinglist API
│   ├── api/followerslist/route.ts  -> followerslist API
│   ├── api/v1/instance/route.ts -> auth
│   ├── api/v1/apps/route.ts.    -> auth
│   ├── api/v1/accounts/verify_credentials/route.ts -> auth
│   ├── api/v1/statuses/route.ts -> Write Post
│   ├── api/v1/timelines/_home_back/route.ts -> timeline(Depreacted)
│   ├── api/v1/media/route.ts -> Image upload
│   ├── api/v1/media/[id]/route.ts  -> Image Delete 
│   ├── api/v1/instance/rules/route.ts -> Feature not implemented.
│   ├── api/v1/instance/domain_blocks/route.ts -> Feature not implemented.
│   ├── api/v1/filters/route.ts -> Feature not implemented.
│   ├── api/v1/lists/route.ts -> Feature not implemented.
│   ├── api/v1/announcements/route.ts -> Feature not implemented.
│   ├── api/v1/timelines/_public_back/route.ts -> Feature not implemented.(Deprecated)
│   ├── api/v1/timelines/[type]/route.ts -> Timeline API
│   ├── api/v1/statuses/[id]/context/route.ts -> Post Check,Delete
│   ├── oauth/authorize/route.ts -> auth
│   ├── oauth/token/route.ts -> auth
│   ├── oauth/login-and-authorize/route.ts -> Tursky,Pinafore login processing
│   ├── oauth/revoke/route.ts -> Feature not implemented.
│   ├── api/v1/search/home/route.ts -> search
│   ├── api/v2/search/home/route.ts -> search
│   ├── api/v2/notifications/policy/route.ts-> Feature not implemented.
│   ├── api/v1/accounts/[id]/followers/route.ts -> followers
│   ├── api/v1/accounts/[id]/following/route.ts -> following
│   ├── api/v1/statuses/[id]/route.ts  -> Post delete(pinafore)
│   ├── api/v1/statuses/[id]/favourite/route.ts -> favourite(for pinafore)
│   ├── api/v1/statuses/[id]/unfavourite/route.ts -> unfavourite(for pinafore)
│   ├── api/v1/statuses/[id]/reblog/route.ts  -> reblog[boost](for pinafore)
│   ├── api/v1/statuses/[id]/unreblog/route.ts  -> unreblog[unboost](for pinafore)
│   ├── api/auth/signup/route.ts        -> Website Signup
│   ├── api/auth/login/route.ts         -> Website Login
│   ├── api/auth/logout/route.ts        -> Website Logout
│   ├── api/auth/refresh/route.ts       -> Refresh Token
│   ├── api/cleanup-orphan/route.ts     -> post,outbox clean up
│   ├── api/auth/me/route.tsx           -> Login Check
│   ├── auth/signup/page.tsx            -> Signup UI
│   ├── auth/signup/page.tsx            -> Login UI        
│   ├── users/[username]/
│   │   ├── statuses/[id]/route.ts -> Indivisual Post
│   │   ├── route.ts               -> Acotr Information
│   │   ├── followers/route.ts     -> Followers List
│   │   ├── following/route.ts     -> Following List
│   │   ├── inbox/route.ts         -> Inbox
│   │   └── outbox/route.ts        -> outbox
│   ├── usersui/[username]/
│   │   ├── page.tsx               -> Timeline UI(Server, 404)
│   │   ├── ClientPage.tsx.        -> Timeline UI(Client,Call Active Themes)
│   │   └── _components/themes/
│   │       ├── themeex/ThemeexTheme.tsx      -> Example Theme
│   │       ├── themeex/FollowersList.tsx     -> Theme Example, FollowersList
│   │       ├── themeex/FollowingList.tsx     -> Theme Example, FollowingList
│   │       ├── themeex/NotificationsList.tsx -> Theme Example, NotificationsList
│   │       ├── themeex/TimelineList.tsx      -> Theme Example, TimelineList
│   │       ├── pinafore/PinaforeTheme.tsx -> Theme 1
│   │       ├── pinafore/FollowersList.tsx -> Theme 1, FollowersList
│   │       ├── pinafore/FollowingList.tsx -> Theme 1, FollowingList
│   │       ├── pinafore/NotificationsList.tsx -> Theme 1, NotificationsList
│   │       ├── pinafore/TimelineList.tsx  -> Theme 1, TimelineList
│   │       ├── mastodon/MastodonTheme.tsx -> Theme 2
│   │       └── minimal/MinimaltTheme.tsx  -> Theme 3
│   ├── layout.tsx, page.tsx, globals.css
│   └── favicon.ico
├── lib/
│   ├── theme.tsx              -> Theme Provider
│   ├── watchThemes.ts         -> Check real-time theme changes
│   ├── auth.ts                -> Authentication, User Management
│   ├── ap.ts                  -> Follow,Undo,Create,Likes,Announce
│   ├── visibility.ts          -> Visibility(Public,Unlisted,Private,Direct)
│   └── db.ts                  -> DB connection
├── data/
│   ├── keys/userIDs/          -> private.pem, public.pem(New)
│   └── keys/                  -> private.pem, public.pem(legacy)
├── data.sqlite                -> Database(1/3)
├── data.sqlite-wal            -> Database(2/3)
├── data.sqlite-shm            -> Database(3/3)
├── Caddyfile                  -> https 
├── instrumentation.ts         -> Background Server
├── proxy.ts                   -> middleware.ts - >proxy.ts(for Nextjs16)
├── postcss.config.mjs         -> for Nextjs16
└── package.json

📁 프로젝트 시작 / Project Start


📁 코드 수정 / Code Modification

✔️ 타임라인에서 데이터가 없으면 탭사라지는 오류 수정
Fixed an error where the tab would disappear when there was no data in the timeline.

✔️ 로그인하지 않으면 홈탭은 로컬API를 호출
If not logged in, the Home tab calls the local API

— app/usersui/[username]/_components/themes/Themeex/TimelineList.tsx

  const {
    flatData,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useCursorPagination({
... ...

      // ✅ myapp61 - API 주소 수정 / modify API Address
      // - fetcher 안에서 직접 로그인 여부 체크 하기 / Check login status directly within the fetcher.
      let me: string | null = null;
      try {
        const meRes = await fetch(`/api/auth/me`, { credentials: 'include', cache: 'no-store' });
        if (meRes.ok) {
          const j = await meRes.json();
          me = j.username || null;
        }
      } catch {}

      const effectiveUser = me || currentUser;

      let url = '';
      if (tab === 'home') {
        if (effectiveUser) {
          url = `/api/v1/timelines/home?${params.toString()}`;
        } else {
          params.set('local', 'true');
          url = `/api/v1/timelines/public?${params.toString()}`;
        }
      } else if (tab === 'local') {
        params.set('local', 'true');
        url = `/api/v1/timelines/public?${params.toString()}`;
      } else {
        url = `/api/v1/timelines/public?${params.toString()}`;
      }
... ...
  });

  // if (data.length === 0) {
  //   return <div className="p-5 text-[#999]">타임라인이 비어있습니다 / No posts</div>;
  // }

  return ( ... ...

      {/* ✅ myapp61 - No posts는 selector 아래에 표시 / "No posts" is displayed below the selector. */} 
      {data.length === 0 && (
        <div className="p-10 text-center text-[#999]">타임라인이 비어있습니다 / No posts in {tab}</div>
      )}
... ...
);

1)로그인 부분은 서버가 아닌 클라이언트 부분에서는 getUser함수로 인증 체크할 수 없음
Regarding the login functionality, authentication cannot be verified using the getUser function on the client side; this must be handled on the server side.

2)클라이언트는 인증 확인을 위해 /api/auth/me 라우트 사용함
The client uses the /api/auth/me route to verify authentication.

3)로그인 한 경우 home라우트 로그인하지 않으면 public라우트로 이동
If logged in, navigate to the home route; if not logged in, navigate to the public route.


✔️ 타임라인 Unknown 및 오류 / Timeline Unknown and Errors

— app/api/v1/timelines/[type]/route.ts

1)타임라인 API에서 acct값을 잘못 줘서 발생하는 오류
An error caused by providing an incorrect ‘acct’ value in the Timeline API.

    return {
      id: String(row.id),
      uri: longId, url: longId,
      account: {
        // id: isMy ? accountId : `remote_${row.username}`, ✅ myapp61
        id: isMy ? accountId : `remote_${row.username}@${acctDomain}`,
        username: row.username, 
        // acct: `${row.username}@${DOMAIN}`, ✅ myapp61
        acct: displayAcct, 
        //display_name: row.username, 
        display_name: accountUsername,
        avatar: `https://${DOMAIN}/icon.png`, avatar_static: `https://${DOMAIN}/icon.png`,
        header: `https://${DOMAIN}/header.png`, header_static: `https://${DOMAIN}/header.png`,
      },
... ...
}

✔️ FollowingList,FollowerList UI 오류/error

— app/usersui/[username]/_components/theme/pinafore/FollowingList.tsx

— app/usersui/[username]/_components/theme/pinafore/FollowersList.tsx

 <div className="w-9 h-9 rounded-full bg-[#6364ff] text-white flex items-center justify-center font-extrabold shrink-0">
... ...
          {/* <button className="ml-auto px-3 py-1 bg-[#6364ff] text-white rounded-full text-xs font-bold hover:bg-[#5556ee]">
            Following
          </button> */} --> or Delete
# v1 API
https://aloy-horizon.duckdns.org/api/v1/timelines/public 
https://aloy-horizon.duckdns.org/api/v1/timelines/public?local=true

# pinafore 테마에서 사용하는 이전 API
https://aloy-horizon.duckdns.org/api/timeline?username=user1&type=home

✔️ 리모트 글에도 DELETE버튼 보이는것 수정
Fixed the issue where the DELETE button was visible on remote posts.

— 로그인 후 내가 작성한 글에만 DELETE버튼 보임
The DELETE button appears only on posts I have written after logging in.

      // ✅ myapp61
      const withMine = arr.map((p:any) => {
        const acct = p.account?.acct || '';
        const username = p.account?.username || p.username || '';
        const acctDomain = acct.includes('@')? acct.split('@')[1] : DOMAIN;
        const isLocalAccount = acctDomain === DOMAIN;

        return {
        ...p,
          isMine:!!(currentUser && isLocalAccount && username === currentUser)
        };
      });  
... ...              
  {/* {currentUser && isMine && (
                  <button onClick={() => onDelete(p.id)} className="text-[#e0245e] ml-auto text-xs hover:underline">
                    🗑 Delete
                  </button>
                )} */}
                {/* ✅ myapp61 */}
                {isMine && (
                  <button onClick={() => onDelete(p.id)} className="text-[#e0245e] ml-auto text-xs">
                    🗑 Delete
                  </button>
                )}

✔️ SNS페이지가 처음 실행될떄 타임라인이 비어있는 걸로 표시되는 오류
An error where the timeline appears empty when the social media page is first launched.

— app/usersui/[username]/ClientPage.tsx

  // ✅ myapp60 + myapp61
  // - 페이지네이션은 TimelineList가 담당, 여기선 빈 배열로 시작
  // - Pagination is handled by TimelineList; start with an empty array here.
  useEffect(() => {
    if (!username) return;
    //setTimeline([]);
    setLoading(false);
  }, [username]);

📁 테스트 / Test

✔️ Unknown error

Unknown error

✔️ 팔로잉,팔로워리스트 UI 오류,알림데이터 중복 처리
UI errors in following/follower lists; handling of duplicate notification data.

Notification

✔️ 리모트 서버 삭제금지,액터 정확히 표시,리모트 서버아이콘표시
Prevent remote server deletion, display actors accurately, show remote server icons.

Remote server

마태복음 21장 22절 / Matthew 21: 22

“너희가 기도할 때에 무엇이든지 믿고 구하는 것은 다 받으리라 하시니라”

“And everything you ask in prayer, believing, you will receive.”

Leave a Reply