Commit Graph
12 Commits
Author SHA1 Message Date
ghassanandClaude Opus 4.7 341e94a4f8 perf(user): cursor + simple pagination on /liked and /history
- /liked: switch Laravel paginate(12) to cursorPaginate(24). Cursor
  pagination matches the Phase 2 feed endpoint pattern: stable across
  inserts (unlike ?page=N which can duplicate or skip rows when a new
  like lands between page fetches) and loads a bounded slice no matter
  how many thousands of likes the user accumulates.
- /history: switch from a get()-all plus in-memory sort to a joined
  simplePaginate(48) at the DB layer. A heavy user who's watched
  thousands of videos would previously fetch every video row into
  memory on each history page load — now the query selects a bounded
  page of (video_views + videos) pairs. Duplicates within a page
  collapse via collect()->unique('id').

Channel videos tab stays non-paginated for now — it needs a dedicated
JSON endpoint before it can share the Phase 2 /videos/feed/more
infinite-scroll wiring. Flagged as follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-10-21 12:09:00 +03:00
ghassanandClaude Opus 4.7 133ab6e623 fix(feeds): trending windows 24/168/720, music newest-first, channel popular tiebreak
- Trending: window options are now 24 / 168 / 720 h (Today / This Week
  / This Month) and the controller snaps the ?hours param to one of
  those values instead of clamping to [24, 168] — which silently made
  the "This Month" tab show one-week data. Ranking is pure in-window
  view count, with likes and newest createdAt as the tiebreaks (not
  the old weighted sum of views + velocity + recency bonus + likes,
  which was impossible to reason about and hid videos that genuinely
  led the window).
- Music + /videos?filter=music: previously the branch skipped the
  latest() call so Eloquent fell back to id ASC and the music tab
  opened on the oldest uploads. Now both branches share one
  ->latest() call.
- Channel Popular sort: order by views desc, likes desc, created_at
  desc so two equally-viewed videos no longer flip order between
  loads.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-10-21 10:06:54 +03:00
ghassanandClaude Opus 4.7 a25af30700 fix(channel): grid, scoreboard thumb, sort hash, visitor privacy
Audit fixes against /channel/{slug}:

1. Fluid video grid — repeat(auto-fill, minmax(260px, 1fr)) replaces
   the three fixed breakpoints (3/2/4 cols at 1101/1500/… px) that
   produced different card widths and could overflow 390 / 1280 /
   1920. min-width:0 on every grid child so a long unbroken title
   (CJK, "SPARTAWORRIOR") can't widen its track past 1fr.
2. Scoreboard thumbnail — stop including vs-mini + scorebar-mini on
   match cards. Those partials leaked fighter names, "AKA/AO",
   "ROUND 1", "0:00" into the card DOM, showing stale 0-0 for
   finished matches and breaking title layout at narrow widths. The
   regular <img> above is the thumbnail now; VS intro + live scorebar
   still render on the full match player page where they belong.
3. Sort pills — Latest/Popular/Oldest now append #videos so the page
   stays on the Videos tab after reload instead of jumping to Wall.
4. Shorts tab — always render for the owner (so the "My Shorts"
   sidebar link always lands somewhere), with an empty-state card
   when no shorts exist. Visitors still see it only when shorts > 0.
5. Subscriptions sidebar link — href="#" replaced by a real
   /feed/subscriptions route backed by UserController@subscriptionsFeed
   that reuses the videos/index view with the subscription feed.
6. Header view count — totalViews now sums video_views over public
   videos for visitors (owner still sees the full total). Previously
   leaked unlisted and private video view counts.
7. Card redundancy — new hideChannelInfo prop on <x-video-card/>
   suppresses the per-card avatar + channel-name row. The channel
   page passes it; everywhere else keeps the row.
9. Decorative logo — the second <img alt="Play"> in the responsive
   header pair now has alt="" so a screen reader doesn't announce
   "Play Play". ⋮ menu button gets aria-label="More actions".
10. Privacy — age, gender, location and horoscope strip now only
    render to the owner on the channel header (horoscope strip is
    also allowed when the compatibility match-up is being shown to
    a signed-in visitor). Joined-month stays public.
11. Notifications dropdown — initial state is "No notifications"
    not an indefinite "Loading…". Opening the panel now shows a
    spinner while fetching, surfaces a Retry button on error, and
    bails out of the "Loading…" state on non-ok HTTP responses.

Title clamp — .yt-video-title is now a 2-line box with
overflow-wrap:anywhere so CJK titles and long words wrap mid-word
and can't widen the card past its track.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-10-21 10:03:39 +03:00
ghassanandClaude Opus 4.8 8ea63a6720 Bust avatar/banner cache so new image shows on all pages
After my previous fix the upload succeeds, but the avatar path is always
.../profile/avatar.<ext>, so its media URL never changes. Pages other than the
channel (which cache-busts with ?t=) kept serving the browser-cached OLD image
— the user "still saw the old avatar" on /videos.

- avatar_url / banner_url accessors append ?v=<updated_at timestamp>.
- updateAvatar / updateBanner now bump updated_at explicitly (the path is
  unchanged, so Eloquent wouldn't otherwise touch it), changing ?v so every
  page fetches the new image.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-29 00:39:47 +03:00
ghassanandClaude Opus 4.8 5d4d21dcec Fix avatar/banner showing broken right after cropping & saving
The cropper's onAvatarSaved/onBannerSaved callback used the url from
image.upload, which points at the temp buffer file. updateAvatar/updateBanner
then move that temp file to the NAS profile dir and delete the local copy, so
the url is dead the moment it's used — the avatar/banner rendered broken until
the next page load (the file itself was saved fine).

- updateAvatar/updateBanner now return the canonical media route URL
  (route('media.avatar'|'media.banner', $relPath)), matching the model's
  avatar_url/banner_url accessors and the project's no-asset('storage/...') rule.
- The image-cropper prefers the update endpoint's returned url over the temp
  image.upload url; falls back to the old behavior when none is returned.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-29 00:31:33 +03:00
ghassan 73527f3781 Add sports-match type, device tracking, profile visits, and share refactor
- New SportsMatch model/controller and sports UI components/modal
- Move share-modal to a reusable x-share-modal/x-share-button component
- Add VideoSharedWithUser notification and share-to-members flow
- Device/user-agent tracking on views, downloads, share accesses
- ProfileVisit model + migration; subscription source tracking
- Email thumbnail support; remove stale TODO files
2026-05-29 01:50:28 +03:00
ghassanandClaude Opus 4.7 66fd78c10f Add multi-language audio tracks and self-hosted flag-icons
Introduce per-video language support and multiple audio tracks
(VideoAudioTrack model + migrations for language, description, title),
a reusable language-select component, and a track-editor form. Bundle
the self-hosted flag-icons v7.2.3 library and a NAS auto-sync command.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-05-22 21:32:52 +03:00
ghassanandClaude Sonnet 4.6 f8d13457fa Add full notification preferences system
Users can now control which in-app and email notifications they receive
from their Settings tab on their channel page.

Bell (in-app) preferences:
- New comment on my video (default: on)
- Reply to my comment (default: on)
- Comment liked (default: on)
- Video liked (default: on)
- New subscriber (default: on)
- New video from channels I follow (default: on)
- New post from channels I follow (default: on)
- New user registration — super admins only (default: on)

Email preferences (same set plus):
- Comment liked (default: off — too noisy)
- Video liked (default: off — too noisy)
- New post from channels I follow (default: off)
- My video finished processing (default: on)
- Weekly activity digest every Monday (default: on)
- New user registration — super admins only (default: on)

Implementation:
- Migration: notification_preferences JSON column on users table
- User::notificationPref($key) helper with typed defaults
- All existing notification classes updated to check prefs in via()
- 4 new notification classes: NewSubscriberNotification,
  VideoLikedNotification, NewPostNotification, WeeklyDigestNotification
- 8 new email views matching existing dark theme
- SendWeeklyDigest artisan command, scheduled every Monday 09:00
- NewSubscriberNotification wired into UserController::toggleSubscribe
- VideoLikedNotification wired into UserController::toggleLike
- NewPostNotification wired into PostController::store (to all subscribers)
- Bell renderer updated for new_subscriber, video_like, new_post types
- Preferences saved via AJAX (POST /settings/notifications) — instant
  toggle with automatic revert on failure

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-16 23:47:28 +03:00
ghassanandClaude Sonnet 4.6 c160242dbc WIP: storage-fix-local-nas work before playlist controls feature
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-16 11:15:20 +03:00
ghassanandClaude Sonnet 4.6 0b2e95ea65 Add NAS file manager integration and all pending platform changes
- Installed p7h/nas-file-manager package via private VCS repo
- Published config/nas-file-manager.php with super_admin middleware restriction
- Added NAS env vars to .env.example
- Created admin/nas-storage page with connection info panel and file browser widget
- Added NAS Storage link to admin sidebar (super_admin only)
- Added SuperAdminController@nasStorage method and admin.nas-storage route
- Includes all accumulated branch changes: profile wall, 2FA, audit logs,
  settings panel, country/phone/timezone components, posts, slideshow,
  playlist shares, video downloads/shares, comment likes, notifications,
  social links, and more

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-13 13:24:32 +03:00
ghassan 062c0e896f latest update 2026-03-11 11:21:33 +03:00
ghassan 5253f89b63 Add video platform features: authentication, video management, user profiles, likes/views tracking
- Added authentication controllers (Login, Register)
- Added UserController for user profile management
- Added VideoController with full CRUD operations
- Added Video model with relationships (user, likes, views)
- Added User model enhancements (avatar, video relationships)
- Added database migrations for video_likes, video_views, user_avatar, video_visibility
- Added CompressVideoJob for video processing
- Added VideoUploaded mail notification
- Added authentication routes
- Updated web routes with video and user routes
- Added layout templates (app, plain, partials)
- Added user views (profile, settings, channel, history, liked)
- Added video views (create, edit, index, show)
- Added email templates
2026-02-25 00:03:02 +00:00