News:

SMF - Just Installed!

Main Menu

Recent posts

#31
Announcements & Releases / v1.1.13
Last post by hitsumo - Jul 16, 2026, 05:45 PM
# Anime Tracker 1.1.13

**Release date:** 2026-07-16

## New: Personal list tab

- **The main list page now has "General List" / "Personal List" tabs.** A
  slim tab bar sits between the pagination bar and the list table.
  - **General List** - the whole catalog (the previous default behaviour;
    nothing changed).
  - **Personal List** - only the anime you have set a watch status on. That
    is, every status EXCEPT "Not Selected": Watched, Watching, Plan to Watch,
    On Hold, Dropped.
- **An anime enters your personal list the moment you pick a status.**
  Setting an anime's status to anything other than "Not Selected" (via the
  in-list +/- controls or the details page) makes it appear on the Personal
  List tab. Setting it back to "Not Selected" removes it.
- **The tab keeps your current search, filters and sort.** While on the
  Personal List tab, the genre / status / letter / emotion filters and search
  all work as usual, scoped to anime with a selected status. Switching tabs
  returns you to the first page.
- **The tabs only show for users who have a personal list.** They are always
  visible on your own install (self-host). In multi-user mode a logged-out
  visitor has no personal list, so the tab bar is not shown to them.

## New: Default list preference

- **The List Settings page gains a "Default List" selector.** It chooses which
  tab is selected when the anime list page opens: **General List** (the previous
  behaviour) or **Personal List**. It is a dropdown, like the interface-language
  selector, and saves as soon as you pick a value.
- **It is per-user.** The preference affects only you (stored in the `user_pref`
  table) and never touches other users.
- **Clicking a tab overrides the preference.** Even if your default is Personal
  List, clicking the "General List" tab switches you for that visit; the next
  time you open the page your default is applied again.

## New: List Settings tabs

- **The List Settings page is now split into tabs.** There are three:
  - **Import/Export** - Export List, Import List, Import MyAnimeList List,
    Import AniList List.
  - **General Settings** - Interface Language, Title Language, Default List,
    Adult Content.
  - **Management Settings** - Genres, Tags, Catalog Sync, Episode Count Sync,
    Update. This tab (both its button and panel) is shown only to
    **moderators/admins** and the **self-host owner**; a regular online member
    never sees it (every section inside was already behind a capability gate;
    now the tab itself is hidden too).
  - **Cleanup** - Clear List. Moved to its own tab because it is a destructive
    action, and shown only to **admins** and the **self-host owner** (button and
    panel gated by `canAdmin`; a regular online member and moderators do not see
    it).
- **Switching tabs is instant, with no page reload.** The open tab is
  remembered in the browser; after an import or a sync reloads the page, the
  same tab stays open.
- **Nothing is lost with JavaScript off.** The tab bar is hidden and all
  sections stack as before (progressive enhancement) - no section was moved,
  only grouped.

## How it works (technical)

- The tab is selected with the `?view=personal` URL parameter and is a pure
  query-scope view: it adds `AND ua.watch_status IS NOT NULL` to the main
  list's existing `user_anime` LEFT JOIN. No new table, column or setting is
  needed.
- An invalid or unauthorized `view` value silently falls back to "General
  List" (including for anonymous online visitors), so it cannot be forced via
  the parameter.
- The default-list preference is stored in the per-user `user_pref` key
  `list_view_default` ('all' / 'personal') and written by a new CSRF-protected
  POST endpoint `set_list_view_pref.php`. An explicit `?view=` in the URL (a tab
  click) always overrides the preference, so the tabs always send an explicit
  view and the preserved sort/filter/search links carry the view only when it
  differs from the preference.

## Schema / migration

- `migration/1.1.13/upgrade.sql` only advances the version to 1.1.13; there is
  **no schema change** (no SQL statement to run). The central catalog is not
  affected and requires no manual step.

## Changed / new files

- index.php (General/Personal tab bar, view scope, default-preference cascade,
  tab preserved across filter/search/sort/pagination links, tab CSS)
- list_settings.php (Default List selector section + Import/Export & General
  tabs: tab bar, panel wrappers, tab CSS and JS switching)
- set_list_view_pref.php (new - CSRF-protected preference endpoint)
- lang/tr.php, lang/en.php (index.tab.* + list_settings.section.list_view.* +
  list_settings.tab.*)
- migration/1.1.13/upgrade.sql (new)
- version.txt
#32
Duyurular ve Sürümler / v1.1.13
Last post by hitsumo - Jul 16, 2026, 05:45 PM
# Anime Tracker 1.1.13

**Yayin tarihi:** 2026-07-16

## Yeni: Kisisel liste sekmesi

- **Ana liste sayfasina "Genel Liste" / "Kisisel Liste" sekmeleri eklendi.**
  Sayfalama cubugu ile liste tablosu arasinda duran ince bir sekme cubugu.
  - **Genel Liste** - katalogun tamami (onceki varsayilan davranis; hicbir
    sey degismedi).
  - **Kisisel Liste** - yalnizca izleme durumu SECTIGINIZ animeler. Yani
    "Secim Yapilmamis" DISINDAKI her durum burada gorunur: Izlendi,
    Izleniyor, Izlenme Planlandi, Izleme Ertelendi, Izleme Birakildi.
- **Durum sectiginiz an anime kisisel listenize girer.** Bir animenin
  durumunu "Secim Yapilmamis" disinda herhangi bir degere ayarlamak
  (liste ici +/- ile veya detay sayfasindan) onu Kisisel Liste sekmesinde
  gorunur kilar. Durumu tekrar "Secim Yapilmamis" yaparsaniz kisisel
  listeden cikar.
- **Sekme mevcut aramanizi, filtrelerinizi ve siralamanizi korur.** Kisisel
  Liste sekmesindeyken tur / durum / harf / duygu filtreleri ve arama aynen
  calisir; yalniz secili duruma sahip animeler uzerinde. Sekme degistirince
  ilk sayfaya donulur.
- **Sekmeler yalniz kisisel listesi olan kullaniciya gosterilir.** Kendi
  kurulumunuzda (self-host) her zaman gorunur. Cok kullanicili surumde giris
  yapmamis ziyaretcinin kisisel listesi olmadigindan sekme cubugu onlara hic
  cikmaz.

## Yeni: Varsayilan liste tercihi

- **Liste Ayarlari sayfasina "Varsayilan Liste" secimi eklendi.** Anime listesi
  sayfasi acildiginda hangi sekmenin secili gelecegini belirlersiniz: **Genel
  Liste** (onceki davranis) veya **Kisisel Liste**. Arayuz-dili secimindeki gibi
  bir acilir menudur; sectiginiz an kaydedilir.
- **Kisi bazlidir.** Tercih yalniz sizi etkiler (`user_pref` tablosunda
  saklanir), diger kullanicilara dokunmaz.
- **Sekmeye tiklamak tercihi ezer.** Varsayilaniniz Kisisel Liste olsa bile
  ustteki "Genel Liste" sekmesine tiklayarak o an genel listeye gecebilirsiniz;
  bir sonraki acilista yine varsayilaniniz gelir.

## Yeni: Liste Ayarlari sekmeleri

- **Liste Ayarlari sayfasi sekmelere ayrildi.** Uc sekme var:
  - **Ice/Disa Aktar** - Listeyi Disa Aktar, Listeyi Ice Aktar, MyAnimeList
    Listesini Ice Aktar, AniList Listesini Ice Aktar.
  - **Genel Ayarlar** - Arayuz Dili, Baslik Dili, Varsayilan Liste, Yetiskin
    Icerik.
  - **Yonetim Ayarlari** - Turler, Etiketler, Katalog Senkronizasyonu, Bolum
    Sayisi Senkronizasyonu, Guncelleme. Bu sekme
    (butonu ve paneli) yalnizca **moderator/admin** ve **self-host sahibi** icin
    gorunur; online normal uye bu sekmeyi hic gormez (zaten icindeki her bolum
    yetki kapisinin arkasindaydi, simdi sekmenin kendisi de gizli).
  - **Temizleme** - Listeyi Temizle. Yikici bir islem oldugu icin kendi
    sekmesine alindi ve yalnizca **admin** ile **self-host sahibi** icin
    gorunur (buton ve panel `canAdmin` ile sarili; online normal uye ve
    moderator gormez).
- **Sekme gecisi aninda, sayfa yenilenmeden olur.** Acik sekme tarayıcıda
  hatirlanir; bir ice/disa aktarma veya senkronizasyon sonrasi sayfa yenilense
  bile ayni sekme acik kalir.
- **JS kapaliyken hicbir sey kaybolmaz.** Sekme cubugu gizlenir ve tum bolumler
  eskisi gibi alt alta gorunur (progressive enhancement) - hicbir bolum
  tasinmadi, yalniz gruplandi.

## Nasil calisir (teknik)

- Sekme, `?view=personal` URL parametresiyle secilir ve tamamen sorgu-kapsamli
  bir gorunumdur: ana listenin mevcut `user_anime` LEFT JOIN'ine
  `AND ua.watch_status IS NOT NULL` kosulu eklenir. Yeni tablo, alan veya ayar
  gerekmez.
- Gecersiz veya yetkisiz `view` degeri sessizce "Genel Liste"ye duser
  (anonim online ziyaretci dahil), yani parametre ile zorlanamaz.
- Varsayilan liste tercihi per-user `user_pref` anahtari
  `list_view_default`'ta ('all' / 'personal') tutulur; yeni endpoint
  `set_list_view_pref.php` (CSRF korumali, POST) yazar. URL'deki acik `?view=`
  parametresi (sekme tiklamasi) her zaman tercihi ezer, bu yuzden sekmeler
  daima acik view yollar ve korunan siralama/filtre/arama baglantilari view'i
  yalniz tercihten farkli oldugunda tasir.

## Sema / migration

- `migration/1.1.13/upgrade.sql` yalnizca surumu 1.1.13'e tasir; **sema
  degisikligi yoktur** (calistirilacak SQL ifadesi yok). Merkez katalog
  etkilenmez, sunucuda elle bir islem GEREKMEZ.

## Degisen / yeni dosyalar

- index.php (Genel/Kisisel sekme cubugu, view kapsami, varsayilan tercih
  cascade'i, sekmenin filtre/arama/siralama/sayfalama baglantilarinda
  korunmasi, sekme CSS'i)
- list_settings.php (Varsayilan Liste secim bolumu + Ice/Disa Aktar & Genel
  sekmeleri: sekme cubugu, panel sarmalamalari, sekme CSS'i ve JS gecisi)
- set_list_view_pref.php (yeni - CSRF korumali tercih endpoint'i)
- lang/tr.php, lang/en.php (index.tab.* + list_settings.section.list_view.* +
  list_settings.tab.*)
- migration/1.1.13/upgrade.sql (yeni)
- version.txt
#33
Announcements & Releases / v1.1.12
Last post by hitsumo - Jul 16, 2026, 08:50 AM
# Anime Tracker 1.1.12

**Release date:** 2026-07-15

## New: Invite request limit

- **The admin can cap how many invite requests may sit in the queue at once
  (e.g. 50, 70, 100).** Once the number of pending requests reaches the limit,
  the public invite-request form (request_invite.php) closes and no new request
  is accepted. Visitors see a "quota full, try again later" notice.
- **The limit counts PENDING requests, so it is self-healing.** When the admin
  invites or rejects a queued request, that slot reopens automatically. The cap
  is based on what is currently waiting, not on all requests ever submitted.
- **You can remove the limit at any time.** Setting the field to `0` removes the
  cap (unlimited) and reopens the form fully.
- The check has two lines: the form is hidden on GET when closed, and the submit
  (POST) side re-validates on the server (it cannot be bypassed with a direct
  POST).

## New: Registration announcement

- **The admin can write a free-text announcement shown on the registration page
  (register.php).** For example: "Invites are limited to 50 people." or "A new
  invite slot opens in one week." The text is not a fixed template - whatever the
  admin types is what appears.
- **Leaving it empty hides the announcement.** With the field blank, no notice is
  shown on the registration screen.
- The text is stored raw and safely escaped on output (no HTML injection); line
  breaks are preserved.

## Admin controls

- Both settings live on the **Registration & Invites** page (admin_invites.php)
  and can only be changed by an **admin**:
  - "Invite Request Limit" card (Invite Requests tab): numeric field 0..100000,
    0 = unlimited. The card shows live status (pending / limit, open or closed).
  - "Registration Announcement" card (Invites tab): free text up to 2000
    characters.

## How it works (technical)

- Two new values are kept in the `settings` key/value table
  (`invite_request_limit`, `register_announcement`); no dedicated schema field
  is needed.
- A new helper `invite_request_limit_state($pdo)` reads the limit and the
  pending count to decide whether the form is open or closed; on a query error
  it fails safe (leaves the form OPEN so legitimate visitors are not locked out).
- **No central-catalog impact** - the settings are app-side only, never sent to
  the central catalog server; NO manual step is required on that host.

## Fix: Turkish characters on the Help pages

- **The Help pages (help.php and the help/ sub-pages) were written in ASCII-safe
  form** (e.g. "Izleme Durumlari", "Nasil Calisir?", "Yardim Icindekiler"). All
  Help text now renders with proper Turkish characters (İ, ç, ğ, ı, ö, ş, ü). The
  content lives in the `help.*` keys of `lang/tr.php`; HTML tags, code samples,
  `#anchor` links, and technical terms (JST, TZ, AnimeSchedule, broadcast_day,
  etc.) are preserved. The English help (`lang/en.php`) was unchanged.
- **The "GitHub page" phrase in the Help footer is now a clickable link**
  (https://github.com/hitsumo/animetracker); it was previously plain text. In
  both the Turkish and English help.
- **A contact email was added to the Help index (help.php):** just below the
  blue line under the title and above the intro text,
  `at@animetracker.uzakdiyarlar.com` (clickable mailto). In both Turkish and
  English (`help.contact`).

## Schema / migration

- `migration/1.1.12/upgrade.sql` seeds the two setting keys with their defaults
  (`INSERT IGNORE`, never clobbers an existing value) and advances the version
  to 1.1.12. There is no schema change.

## Changed / new files

- functions/auth_helpers.php (invite_request_limit_state + 'full' in submit)
- request_invite.php (hide form + closed notice when the queue is full)
- admin/admin_invites.php (limit + announcement cards, admin-only POSTs)
- register.php (announcement banner)
- help.php (contact email line)
- lang/tr.php (invites + help Turkish-character fix + help.contact),
  lang/en.php (invites + footer/contact links), lang/admin_tr.php,
  lang/admin_en.php
- migration/1.1.12/upgrade.sql (new)
- version.txt
#34
Duyurular ve Sürümler / v1.1.12
Last post by hitsumo - Jul 16, 2026, 08:49 AM
# Anime Tracker 1.1.12

**Yayin tarihi:** 2026-07-15

## Yeni: Davetiye talep limiti

- **Yonetici, ayni anda kuyrukta bekleyebilecek davetiye talebi sayisina bir
  limit koyabilir (or. 50, 70, 100).** Bekleyen talep sayisi bu limite
  ulasinca herkese acik davetiye talep formu (request_invite.php) kapanir ve
  yeni talep alinmaz. Ziyaretciye "kontenjan dolu, sonra tekrar dene" bildirimi
  gosterilir.
- **Limit BEKLEYEN talepleri sayar; kendini onarir.** Yonetici bir talebi
  davet edince veya reddedince o slot yeniden acilir - yeni talep alinabilir
  hale gelir. Boylece limit, gecmis tum talepleri degil yalnizca su an isleme
  bekleyenleri baz alir.
- **Limiti istediginiz zaman kaldirabilirsiniz.** Alana `0` yazmak limiti
  kaldirir (sinirsiz) - formu tekrar tam acar.
- Kontrol iki hatlidir: form GET'te kapaliysa hic gosterilmez, ayrica gonderim
  (POST) tarafinda da sunucu yeniden dogrular (dogrudan POST ile asilamaz).

## Yeni: Kayit ekrani duyurusu

- **Yonetici, kayit sayfasinda (register.php) gosterilecek serbest metinli bir
  duyuru yazabilir.** Ornek: "Davetiye 50 kisiliktir." veya "Yeni davetiye
  slotu 1 hafta sonra acilacaktir." Metin secmeli/kaliplasmis degildir; yonetici
  ne yazarsa o gosterilir.
- **Bos birakmak duyuruyu gizler.** Duyuru alani bosken kayit ekraninda hicbir
  not cikmaz.
- Metin ham saklanir, ciktida guvenli kacislanir (HTML enjeksiyonu yok); satir
  sonlari korunur.

## Yonetici kontrolleri

- Her iki ayar da **Kayit ve Davetler** (admin_invites.php) sayfasindadir ve
  **yalnizca yonetici** tarafindan degistirilebilir:
  - "Davetiye Talep Limiti" karti (Davetiye Talepleri sekmesi): sayisal alan
    0..100000, 0 = sinirsiz. Kartta canli durum gosterilir (bekleyen / limit,
    form acik mi kapali mi).
  - "Kayit Ekrani Duyurusu" karti (Davetler sekmesi): 2000 karaktere kadar
    serbest metin.

## Nasil calisir (teknik)

- Iki yeni deger `settings` anahtar/deger tablosunda tutulur
  (`invite_request_limit`, `register_announcement`); ayri bir sema alani
  gerektirmez.
- Yeni yardimci `invite_request_limit_state($pdo)` limiti ve bekleyen talep
  sayisini okuyup formun acik/kapali oldugunu belirler; sorgu hatasinda
  guvenli tarafta kalir (formu ACIK birakir, mesru ziyaretciyi kilitlemez).
- **Merkez katalog etkisi yoktur** - ayarlar yalnizca app tarafindadir, merkez
  katalog sunucusuna hic gitmez; sunucuda elle bir islem GEREKMEZ.

## Duzeltme: Yardim sayfasi Turkce karakterleri

- **Yardim sayfalarinin (help.php ve help/ alt sayfalari) icerigi ASCII-guvenli
  yazilmisti** (or. "Izleme Durumlari", "Nasil Calisir?", "Yardim Icindekiler").
  Tum yardim metinleri artik dogru Turkce karakterlerle gosterilir
  (İ, ç, ğ, ı, ö, ş, ü). Icerik `lang/tr.php` icindeki `help.*` anahtarlarindadir;
  HTML etiketleri, kod ornekleri, capa (#anchor) baglantilari ve teknik terimler
  (JST, TZ, AnimeSchedule, broadcast_day vb.) korunmustur. Ingilizce yardim
  (`lang/en.php`) degismedi.
- **Yardim sayfasi alt bilgisindeki "GitHub sayfasi" ifadesi artik tiklanabilir
  bir baglantidir** (https://github.com/hitsumo/animetracker); daha once duz
  metindi. Hem Turkce hem Ingilizce yardimda.
- **Yardim ana sayfasina (help.php) iletisim e-postasi eklendi:** basliktaki
  mavi cizginin hemen altinda, giris metninin ustunde
  `at@animetracker.uzakdiyarlar.com` (tiklanabilir mailto). Hem Turkce hem
  Ingilizce (`help.contact`).

## Sema / migration

- `migration/1.1.12/upgrade.sql` iki ayar anahtarini varsayilanlariyla tohumlar
  (`INSERT IGNORE`, mevcut degeri ezmez) ve surumu 1.1.12'ye tasir. Sema
  degisikligi yoktur.

## Degisen / yeni dosyalar

- functions/auth_helpers.php (invite_request_limit_state + submit'te 'full')
- request_invite.php (kuyruk doluysa formu gizle + kapali bildirimi)
- admin/admin_invites.php (limit + duyuru kartlari, admin-only POST'lar)
- register.php (duyuru banneri)
- help.php (iletisim e-postasi satiri)
- lang/tr.php (davetiye + yardim Turkce karakter duzeltmesi + help.contact),
  lang/en.php (davetiye + footer/iletisim linkleri), lang/admin_tr.php,
  lang/admin_en.php
- migration/1.1.12/upgrade.sql (yeni)
- version.txt
#35
Announcements & Releases / v1.1.11
Last post by hitsumo - Jul 15, 2026, 10:59 AM
Anime Tracker 1.1.11

Release date:** 2026-07-15

New: AniList import source limit

- **In online (multi-user) mode, a normal member may import from at most 3
  DIFFERENT AniList accounts.** This stops a single member from pulling an
  unbounded number of other people's public lists and flooding the moderation
  queue / catalog.

  - **The same account can be re-synced without limit.** An account you have
    already imported can be pulled again as often as you like without spending
    a new slot (a legitimate case: keep using AniList and come back later to
    re-import).

  - **A slot is consumed only on a real, successful import.** A mistyped name,
    previewing and cancelling, or an error never burns a slot; you can preview
    as much as you like.

  - Usernames are case-insensitive: `Mahmut`, `mahmut` and `MAHMUT` are one
    slot.

 Exemptions

- **Self-host (single-user) installs are never limited** - the sole owner may
  import from as many different names as they want.

- **Moderators and above are exempt** - bulk seeding is their legitimate job.

## Admin controls

- **The limit is configurable.** On the Admin Capabilities page, the "AniList
  import source limit" field sets the number of different accounts (default 3).
  **Setting 0 removes the limit (unlimited)** - an emergency off-valve.

- **An admin can reset a user's limit.** On the User Management page, every
  member who has used sources has a "Reset" button on their row; it clears that
  user's recorded sources so they regain the full allowance.

## How it works (technical)

- A new app-side table `anilist_import_sources` records the DISTINCT AniList
  names each member has used (one row per user, `(user_id, username)` UNIQUE).
  Used-source count = that user's row count.

- The check has two lines: at preview time (WITHOUT hitting AniList, no wasted
  call) and at import time (second defense + recording).

- The limit value lives in the `settings.anilist_import_source_limit` key; it
  needs no dedicated schema column.

- **No central-catalog impact** - this table is app-side only and never reaches
  the central catalog server; no manual step is required there.

## Improvement: Long dropdowns capped at 8 rows

- **Long dropdowns (more than 8 options) now show at most 8 rows, the rest
  scrolling.** For example the main list's "Filter by Genre" and the long
  selects on the form/detail pages used to cover almost the whole screen when
  opened; they are now compact, scrollable menus.

- **Applies site-wide:** the rule is not tied to one menu - every native
  `<select>` with more than 8 options is capped automatically; short menus
  (<=8) stay native.

- On desktop (mouse) the native `<select>` is enhanced into a compact menu;
  the selection is still written to the same form field (submit/filtering
  behavior unchanged). Touch devices keep the native picker. With JS off, the
  native list keeps working.

- `required` menus keep working (the native select is hidden but stays
  focusable, so browser validation is not broken). A very special menu (e.g.
  the genre-ADD picker that resets its own value) can be exempted with
  `data-no-enhance`.

## Security / deployment: main-app .htaccess

- **Added a dedicated `.htaccess` for the main-app document root (`files/`).**
  It 301-redirects http to https and sends HSTS, so the session cookie (written
  with the `Secure` flag in db.php over HTTPS) is always sent - removing the
  "logged in over https but logged out over http" symptom.

- Also: directory listing off, sensitive files denied (config.php, *.sql,
  *.md/*.txt, dotfiles), no web access to include/tooling dirs (functions/,
  migration/, tek_kullanimlik/), and no PHP execution under uploads/. PHP is
  NOT default-denied (the app's endpoints stay public) - this differs from the
  CENTRAL CATALOG server's default-deny `.htaccess`; the two must not be mixed.

## Schema / migration

- `migration/1.1.11/upgrade.sql` creates the new table (idempotent,
  `CREATE TABLE IF NOT EXISTS`). Fresh installs get it from `schema.sql`.

## Changed / new files

- functions/anilist_import_helpers.php (limit helpers)
- list_settings.php (preview + import limit checks, source recording)
- admin/admin_capabilities.php (global limit setting)
- admin/admin_users.php (per-user limit reset)
- lang/tr.php, lang/en.php, lang/admin_tr.php, lang/admin_en.php
- schema.sql (anilist_import_sources table)
- migration/1.1.11/upgrade.sql (new)
- js/select_enhance.js (new - generic dropdown enhancer)
- css/components.css (custom dropdown styles)
- index.php, add_anime.php, edit_anime.php, list_settings.php,
  anime_details.php, admin/admin_users.php, admin/admin_invites.php
  (select_enhance.js script tag; data-no-enhance on the add/edit genre-add
  picker)
- .htaccess (new - main-app docroot: HTTPS enforcement + HSTS + hardening)
- version.txt
#36
Announcements & Releases / v1.1.10
Last post by hitsumo - Jul 14, 2026, 10:44 AM
Anime Tracker 1.1.10

 Release date:** 2026-07-14

New feature

- **Three new broadcast-status values.** An anime's broadcast status is no longer
  limited to "Currently Airing" and "Finished Airing"; three more states can now
  be chosen:
  - **Not Yet Aired** - upcoming anime that has not started airing.
  - **Not Selected** - unspecified / unknown status. New anime forms now default
    to this value, so adding an anime no longer forces a finished/ongoing guess.
  - **Cancelled** - anime whose broadcast was cancelled.
- The new states appear in the add/edit status dropdown, the broadcast-status
  filter on the main page, and the statistics/display surfaces.
- **Automatic "Not Yet Aired" -> "Currently Airing" transition.** "Not Yet Aired"
  is not a dead end: when an anime actually starts broadcasting it flips to
  "Currently Airing" on its own - just as "Currently Airing -> Finished" is
  already automatic. This completes the broadcast-status lifecycle.

 How it works (technical)

- Three values were APPENDED to the `animes.status` enum (and its twin
  `catalog_requests.status`) - appended in place so existing rows keep their
  ordinal and no data is rewritten. Applied automatically on every install via
  `migration/1.1.10/upgrade.sql` (MODIFY is idempotent / re-run-safe).

- Broadcast-status labelling is now single-sourced through the new
  `broadcast_status_helpers.php` (`broadcast_status_label()` /
  `broadcast_status_options()`), replacing the if/elseif that was duplicated at
  every render surface - the same pattern as the watch_status helper family.

- Language-aware labels: the new states are translated in the English UI too
  (`index.broadcast.not_started` / `.unselected` / `.cancelled`).

## Import mapping

- **AniList** status now maps almost one-to-one (previously five states folded
  into two): FINISHED -> Finished, RELEASING/HIATUS -> Ongoing,
  NOT_YET_RELEASED -> Not Yet Aired, CANCELLED -> Cancelled.
- **AnimeSchedule** auto-fill: "Upcoming" -> "Not Yet Aired".
- Unknown / status-less imports (the legacy MAL export carries no airing status)
  now default to "Not Selected" instead of "Finished".

## Automatic transition (Not Yet Aired -> Currently Airing)

- The aired sync (`syncAllOngoingAiredEpisodes`, run from the page and from cron
  via `sync_aired.php`) now sweeps "Not Yet Aired" rows in addition to
  "Currently Airing" ones. The moment AnimeSchedule's timetable shows such a row
  with an ALREADY-aired episode (future-dated episodes are skipped by
  `isTimetableRowAired`), broadcast has begun, so the row is promoted to
  "Currently Airing" (or straight to "Finished" if its whole raw run has already
  aired). No extra API calls - the same weekly timetable request that updates
  ongoing shows also catches the ones that just started. A new `started` counter
  is added to the sync summary (web message + cron STDOUT).
- Limit: promotion only works for animes that have an `anime_schedule_link` and a
  `mal_id`; a "Not Yet Aired" anime lacking those must be moved by hand.
  Promotion does not compute `next_episode_date` (the aired sync never does), so
  the countdown still relies on `broadcast_day`/`broadcast_time` (cosmetic).

## Maintenance tool

- **`tek_kullanimlik/anilist_airing_backfill.php` updated for 1.1.10.** In 1.1.9
  it folded everything into a single "not-finished -> ongoing" bucket; it now
  asks AniList for every animes.mal_id and emits a SEPARATE UPDATE per target
  state (same mapping as anilist_airing_status_to_enum): NOT_YET_RELEASED ->
  Not Yet Aired, CANCELLED -> Cancelled, RELEASING/HIATUS -> Ongoing, FINISHED
  -> Finished. A row is written only when the target differs from its current
  status. Rows where AniList returns a duplicate/inconsistent idMal go to a
  manual-review list (never touched automatically). The "-> Finished" block is
  emitted commented out (a raw flip does not reconcile aired/total the way the
  edit form does). Same pacing/retry/resume design is preserved.

## Central catalog note (IMPORTANT)

- The central catalog server (`catalog_server/`) does NOT run the
  MigrationManager. Its `animes.status` enum must be ALTERed by hand to the same
  five values, otherwise a pushed row carrying a new status is rejected:
 
  ```sql
  ALTER TABLE `animes`
    MODIFY `status` enum('Yayın Tamamlandı','Yayın Devam Ediyor',
      'Yayın Başlamadı','Seçim Yapılmadı','Yayın İptal Edildi') NOT NULL;
  ```
 

## Changed files

- schema.sql (animes.status + catalog_requests.status enums)
- migration/1.1.10/upgrade.sql (new - ALTERs both tables)
- functions/broadcast_status_helpers.php (new helper)
- functions.php (loads the new helper)
- functions/anilist_import_helpers.php (five-state mapping)
- functions/animeschedule_helpers.php (Upcoming mapping + Not-Yet sweep/promote)
- sync_aired.php (started counter in cron summary)
- add_anime.php, edit_anime.php (status dropdown + server-side normalization)
- index.php (filter dropdown)
- recent.php, statistics.php, anime_details.php, pending.php,
  admin/admin_pending.php, admin/admin_catalog_requests.php (label helper)
- list_settings.php (whitelist + defaults + web sync started counter)
- catalog_import.php, catalog_server/admin_push.php (default status)
- lang/tr.php, lang/en.php (three new label keys + started result label)
- tek_kullanimlik/anilist_airing_backfill.php (four-state backfill)
- version.txt

GitHub Download
#37
Announcements & Releases / v1.1.9
Last post by hitsumo - Jul 14, 2026, 08:33 AM
Anime Tracker 1.1.9

Release date:** 2026-07-13

 Improvement

- **Language-aware "no image" placeholder for posterless animes.** Animes with
  no poster used to render a broken image on the list and detail pages; they now
  show a "no image" placeholder that matches the interface language. When you
  switch the interface language the placeholder switches too: "BURADA RESIM YOK"
  in Turkish, "IMAGE NOT HERE" in English.

  - As soon as you add a real poster to an anime, the placeholder disappears on
    its own (the real poster is shown).
  - Every place a poster is shown is covered: list, anime detail, recently
    added, recommendations, series timeline, and pending.

 How it works (technical)

- The placeholder is NOT written to the database; while image_path is empty it
  is chosen at display time by language (new `poster_src()` helper). So there
  are NO per-anime file copies and NO database writes - just two static images.
- Dual-mode: on a catalog client, a posterless anime shows the placeholder in
  ITS OWN language (the placeholder is never sent over the catalog wire).

 Setup note

- Place the two images under `img/` with these names:
  - `img/no_poster_tr.png` (Turkish - "BURADA RESIM YOK")
  - `img/no_poster_en.png` (English - "IMAGE NOT HERE")

 Fix

- **Poster proportions on the detail page.** The cover area on the anime detail
  page stretched portrait posters into a landscape box, making them look
  squashed (an invalid `object-fit` value). Posters now display at their correct
  aspect ratio (the cover box was made portrait: 400x600). This applies to the
  new "no image" placeholder too - it also shows at the correct ratio.

 Notes

- No schema change in this release (code plus two images only).

Maintenance / housekeeping

- One-time CLI tools were gathered under `files/tek_kullanimlik/`
  (anilist_isadult_backfill.php was moved there) so they do not mix with the
  main files.

- New maintenance tool: `tek_kullanimlik/anilist_airing_backfill.php` - finds
  animes recorded as "finished" in the catalog that AniList still reports as
  airing/upcoming and emits UPDATE SQL (catalog rows added without airing info
  default to "finished"). Modeled on the isAdult backfill; does not touch the DB.

Changed files

- functions/anime_helpers.php (new poster_src() helper)
- index.php, anime_details.php, recent.php, recommendations.php,
  series_timeline.php, pending.php (poster renders via poster_src)
- css/base.css (.anime-cover object-fit fix + portrait box)
- img/no_poster_tr.png, img/no_poster_en.png (new images)
- tek_kullanimlik/anilist_isadult_backfill.php (moved here)
- version.txt
- migration/1.1.9/upgrade.sql (new, no-op)

Download Github
#38
Announcements & Releases / v1.1.8
Last post by hitsumo - Jul 13, 2026, 07:38 AM
Anime Tracker 1.1.8

Release date:** 2026-07-12

Improvement

- **Saving an anime is now much faster.** When you add or edit an anime, the
  app used to resend the ENTIRE catalog to the central server; as the catalog
  grew (thousands of animes) this made saving wait on a full resync. Now only
  the relevant anime's **series** (rows sharing the same series name) is sent,
  or just that one anime when it has no series name. So saving pushes a handful
  of records instead of the whole catalog.

## For administrators

- **"Push Entire Catalog" button on the edit page (admin only).** Since the
  normal "Update" now sends only the relevant series, an admin who wants to
  resend the whole catalog to the server at once uses this button. (The
  existing manual push tool only worked on localhost; this button works online.)
 Notes

- No schema change in this release.
- Bulk approval (promoting pending items) and adding a chronology note still
 Interface

- List/detail buttons ("Anime List", "Anime Details", etc.) changed from blue
  to teal.

 Changed files

- admin/catalog_push.php
- edit_anime.php
- add_anime.php
- lang/tr.php, lang/en.php
- css/list.css
- version.txt
- migration/1.1.8/upgrade.sql (new, no-op)

Download Github
#39
Announcements & Releases / v1.1.7
Last post by hitsumo - Jul 12, 2026, 07:21 PM
Anime Tracker 1.1.7

Release date:** 2026-07-12

 Fixed

- **Imported adult (+18) titles are now flagged correctly.** When you import
  your AniList list, titles marked adult on AniList are now also flagged +18 in
  the catalog. Those titles then respect the "hide adult content" preference and
  the +18 filter.
 
  - The previous version (1.1.6) did not read this information, so adult titles
    could enter the catalog unflagged (visible). 1.1.7 closes that gap.
  - The +18 flag is carried both on a personal (self-host) direct add and on the
    online catalog-suggestion -> moderator-approval path.

- **Large AniList lists now import reliably.** Because of AniList's per-minute
  request limit, importing a very large (hundreds of entries) list could stop
  midway with a "rate limit reached" error. Page requests are now paced under
  the limit, and if the limit is hit the import waits briefly and retries the
  same page instead of stopping, so large lists finish. (As a result, importing
  a very large list may take a little longer.)
 

## Fixing titles imported earlier (optional)

- Titles you imported with AniList BEFORE 1.1.7 may have been left unflagged. A
  command-line tool corrects them in one pass:
 
  ```
  php anilist_isadult_backfill.php > isadult_backfill.sql
  ```
 
  The tool changes nothing in the database; it only asks AniList and generates an
  `UPDATE` SQL statement for the adult titles. You review the generated file and
  run it in your database manager (e.g. phpMyAdmin).
 

 Notes

- This release has a real schema change: an +18 flag column is added to the
  online catalog-suggestion queue (migration/1.1.7). The migration runs
  automatically; no manual action is needed on the central catalog server.
- The +18 flag on the anime table already existed; what changed is that the
  import path now fills it in.

Changed files

- functions/anilist_import_helpers.php
- list_settings.php
- admin/admin_catalog_requests.php
- anilist_isadult_backfill.php (new, one-time tool)
- schema.sql
- migration/1.1.7/upgrade.sql (new)
- version.txt

Download Github

#40
Announcements & Releases / v1.1.6
Last post by hitsumo - Jul 11, 2026, 09:16 PM
Anime Tracker 1.1.6

Release date:** 2026-07-11

New

- **Import your AniList list.** You can now bring your AniList anime list into
  the app. In the new "Import AniList List" section on the List Settings page,
  enter your AniList **username**; your public anime list is fetched from
  AniList.

  - **Preview first, write after:** A preview is shown first - how many entries
    were read, how many matched the catalog, how many are already in your list,
    and how many are not in the catalog. Nothing is saved until you confirm.
  - **Pick by status:** From the preview you can choose which watch statuses to
    import (Watching, Completed, On Hold, Dropped, Plan to Watch). AniList's
    "rewatching" maps to Watching and "paused" to On Hold.

  - **Two import types:** Choose in the preview - "import the list with watch
    state" (status, episodes, dates and notes are written to your list) or
    "import content only" (the anime are added only to your catalog/database; no
    personal watch state is imported). "Content only" is handy for seeding the
    catalog from a public list without inheriting its watch history. **The
    default type is "content only"**; pick "with watch state" if you want to
    import your own list with its statuses.

  - **Overwrite option:** By default entries already in your list are skipped;
    an "overwrite" option updates them instead. (This option applies only to the
    "with watch state" type.)

  - **Entries not in the catalog:** In the online edition they are sent as
    catalog suggestions (for moderator approval); in a personal (self-host)
    install they are added locally - the same behavior as the MyAnimeList
    import.

  - Watch status, watched episode count, start/finish dates and notes are
    imported.

  - **Correct airing status:** For an anime not in the catalog, its airing
    status (finished / ongoing) is taken from AniList data - added directly on a
    personal install, or carried on the catalog suggestion and used at approval
    time online. So a still-airing anime is not mistakenly recorded as
    "finished". (This does not apply to the MyAnimeList import, as the file does
    not carry airing status.)

## Notes

- Your AniList list must be **public** for this to work.
- The server contacts AniList during the import, so an internet connection is
  required. Very long lists are fetched page by page.
- No schema or migration change (migration/1.1.6 is a no-op ring). Matching uses
  the same identity (MAL id) as the MyAnimeList import; no new tables or
  columns are added.

Changed files

- functions/anilist_import_helpers.php (new)
- functions.php
- list_settings.php
- lang/tr.php, lang/en.php
- css/components.css
- version.txt
- migration/1.1.6/upgrade.sql

Download GitHub