qBitrr2 5.5.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qBitrr/__init__.py +14 -0
- qBitrr/arss.py +7100 -0
- qBitrr/auto_update.py +382 -0
- qBitrr/bundled_data.py +7 -0
- qBitrr/config.py +192 -0
- qBitrr/config_version.py +144 -0
- qBitrr/db_lock.py +400 -0
- qBitrr/db_recovery.py +202 -0
- qBitrr/env_config.py +73 -0
- qBitrr/errors.py +41 -0
- qBitrr/ffprobe.py +105 -0
- qBitrr/gen_config.py +1331 -0
- qBitrr/home_path.py +23 -0
- qBitrr/logger.py +235 -0
- qBitrr/main.py +790 -0
- qBitrr/search_activity_store.py +92 -0
- qBitrr/static/assets/ArrView.js +2 -0
- qBitrr/static/assets/ArrView.js.map +1 -0
- qBitrr/static/assets/ConfigView.js +4 -0
- qBitrr/static/assets/ConfigView.js.map +1 -0
- qBitrr/static/assets/LogsView.js +2 -0
- qBitrr/static/assets/LogsView.js.map +1 -0
- qBitrr/static/assets/ProcessesView.js +2 -0
- qBitrr/static/assets/ProcessesView.js.map +1 -0
- qBitrr/static/assets/app.css +1 -0
- qBitrr/static/assets/app.js +11 -0
- qBitrr/static/assets/app.js.map +1 -0
- qBitrr/static/assets/build.svg +3 -0
- qBitrr/static/assets/check-mark.svg +5 -0
- qBitrr/static/assets/close.svg +4 -0
- qBitrr/static/assets/download.svg +5 -0
- qBitrr/static/assets/gear.svg +5 -0
- qBitrr/static/assets/live-streaming.svg +8 -0
- qBitrr/static/assets/log.svg +3 -0
- qBitrr/static/assets/logo.svg +48 -0
- qBitrr/static/assets/plus.svg +4 -0
- qBitrr/static/assets/process.svg +15 -0
- qBitrr/static/assets/react-select.esm.js +7 -0
- qBitrr/static/assets/react-select.esm.js.map +1 -0
- qBitrr/static/assets/refresh-arrow.svg +3 -0
- qBitrr/static/assets/table.js +5 -0
- qBitrr/static/assets/table.js.map +1 -0
- qBitrr/static/assets/trash.svg +8 -0
- qBitrr/static/assets/up-arrow.svg +3 -0
- qBitrr/static/assets/useInterval.js +2 -0
- qBitrr/static/assets/useInterval.js.map +1 -0
- qBitrr/static/assets/vendor.js +2 -0
- qBitrr/static/assets/vendor.js.map +1 -0
- qBitrr/static/assets/visibility.svg +9 -0
- qBitrr/static/index.html +33 -0
- qBitrr/static/logov2-clean.svg +48 -0
- qBitrr/static/manifest.json +23 -0
- qBitrr/static/sw.js +87 -0
- qBitrr/static/vite.svg +1 -0
- qBitrr/tables.py +143 -0
- qBitrr/utils.py +274 -0
- qBitrr/versioning.py +136 -0
- qBitrr/webui.py +3114 -0
- qbitrr2-5.5.5.dist-info/METADATA +1191 -0
- qbitrr2-5.5.5.dist-info/RECORD +64 -0
- qbitrr2-5.5.5.dist-info/WHEEL +5 -0
- qbitrr2-5.5.5.dist-info/entry_points.txt +2 -0
- qbitrr2-5.5.5.dist-info/licenses/LICENSE +21 -0
- qbitrr2-5.5.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from threading import RLock
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from peewee import Model, SqliteDatabase, TextField
|
|
7
|
+
|
|
8
|
+
from qBitrr.db_lock import with_database_retry
|
|
9
|
+
from qBitrr.home_path import APPDATA_FOLDER
|
|
10
|
+
|
|
11
|
+
_DB_LOCK = RLock()
|
|
12
|
+
_DB_INSTANCE: SqliteDatabase | None = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get_database() -> SqliteDatabase:
|
|
16
|
+
global _DB_INSTANCE
|
|
17
|
+
if _DB_INSTANCE is None:
|
|
18
|
+
path = APPDATA_FOLDER.joinpath("webui_activity.db")
|
|
19
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
20
|
+
_DB_INSTANCE = SqliteDatabase(
|
|
21
|
+
str(path),
|
|
22
|
+
pragmas={
|
|
23
|
+
"journal_mode": "wal",
|
|
24
|
+
"cache_size": -64_000,
|
|
25
|
+
"foreign_keys": 1,
|
|
26
|
+
"ignore_check_constraints": 0,
|
|
27
|
+
"synchronous": 0,
|
|
28
|
+
"read_uncommitted": 1,
|
|
29
|
+
},
|
|
30
|
+
timeout=15,
|
|
31
|
+
check_same_thread=False,
|
|
32
|
+
)
|
|
33
|
+
return _DB_INSTANCE
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class BaseModel(Model):
|
|
37
|
+
class Meta:
|
|
38
|
+
database = _get_database()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class SearchActivity(BaseModel):
|
|
42
|
+
category = TextField(primary_key=True)
|
|
43
|
+
summary = TextField(null=True)
|
|
44
|
+
timestamp = TextField(null=True)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _ensure_tables() -> None:
|
|
48
|
+
db = _get_database()
|
|
49
|
+
with _DB_LOCK:
|
|
50
|
+
# Connect with retry logic for transient I/O errors
|
|
51
|
+
with_database_retry(lambda: db.connect(reuse_if_open=True))
|
|
52
|
+
db.create_tables([SearchActivity], safe=True)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def record_search_activity(category: str, summary: str | None, timestamp: str | None) -> None:
|
|
56
|
+
if not category:
|
|
57
|
+
return
|
|
58
|
+
_ensure_tables()
|
|
59
|
+
if timestamp is not None and not isinstance(timestamp, str):
|
|
60
|
+
timestamp = str(timestamp)
|
|
61
|
+
data: dict[str, Any] = {"summary": summary, "timestamp": timestamp}
|
|
62
|
+
with _get_database().atomic():
|
|
63
|
+
SearchActivity.insert(category=category, **data).on_conflict(
|
|
64
|
+
conflict_target=[SearchActivity.category],
|
|
65
|
+
update=data,
|
|
66
|
+
).execute()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def fetch_search_activities() -> dict[str, dict[str, str | None]]:
|
|
70
|
+
_ensure_tables()
|
|
71
|
+
activities: dict[str, dict[str, str | None]] = {}
|
|
72
|
+
db = _get_database()
|
|
73
|
+
# Connect with retry logic for transient I/O errors
|
|
74
|
+
with_database_retry(lambda: db.connect(reuse_if_open=True))
|
|
75
|
+
try:
|
|
76
|
+
query = SearchActivity.select()
|
|
77
|
+
except Exception:
|
|
78
|
+
return activities
|
|
79
|
+
for row in query:
|
|
80
|
+
activities[str(row.category)] = {
|
|
81
|
+
"summary": row.summary,
|
|
82
|
+
"timestamp": row.timestamp,
|
|
83
|
+
}
|
|
84
|
+
return activities
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def clear_search_activity(category: str) -> None:
|
|
88
|
+
if not category:
|
|
89
|
+
return
|
|
90
|
+
_ensure_tables()
|
|
91
|
+
with _get_database().atomic():
|
|
92
|
+
SearchActivity.delete().where(SearchActivity.category == category).execute()
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{u as qe,f as es,h as ss,i as as,k as Ve,l as ts,j as e,I as Je,R as Ge,m as Ue}from"./app.js";import{r as a,u as Le,f as pe,g as Pe,a as ns,b as cs,c as ds}from"./table.js";import{u as Ie}from"./useInterval.js";import"./vendor.js";const Ye=50,Se=50,Be=500;function gs({loading:d,rows:c,total:m,page:f,totalPages:R,onPageChange:M,onRefresh:L,lastUpdated:I,sort:p,onSort:P,summary:i}){const g=a.useMemo(()=>[{accessorKey:"__instance",header:"Instance",size:150},{accessorKey:"title",header:"Title",cell:o=>o.getValue()},{accessorKey:"year",header:"Year",size:80},{accessorKey:"monitored",header:"Monitored",cell:o=>o.getValue()?e.jsx("span",{className:"table-badge",children:"Yes"}):e.jsx("span",{children:"No"}),size:100},{accessorKey:"hasFile",header:"Has File",cell:o=>o.getValue()?e.jsx("span",{className:"table-badge",children:"Yes"}):e.jsx("span",{children:"No"}),size:100},{accessorKey:"reason",header:"Reason",cell:o=>{const v=o.getValue();return v?e.jsx("span",{className:"table-badge table-badge-reason",children:v}):e.jsx("span",{className:"hint",children:"—"})},size:120}],[]),n=Le({data:c,columns:g,getCoreRowModel:Pe()});return e.jsxs("div",{className:"stack animate-fade-in",children:[e.jsxs("div",{className:"row",style:{justifyContent:"space-between"},children:[e.jsxs("div",{className:"hint",children:["Aggregated movies across all instances"," ",I?`(updated ${I})`:"",e.jsx("br",{}),e.jsx("strong",{children:"Available:"})," ",i.available.toLocaleString(void 0,{maximumFractionDigits:0})," •"," ",e.jsx("strong",{children:"Monitored:"})," ",i.monitored.toLocaleString(void 0,{maximumFractionDigits:0})," •"," ",e.jsx("strong",{children:"Missing:"})," ",i.missing.toLocaleString(void 0,{maximumFractionDigits:0})," •"," ",e.jsx("strong",{children:"Total:"})," ",i.total.toLocaleString(void 0,{maximumFractionDigits:0})]}),e.jsxs("button",{className:"btn ghost",onClick:L,disabled:d,children:[e.jsx(Je,{src:Ge}),"Refresh"]})]}),d?e.jsxs("div",{className:"loading",children:[e.jsx("span",{className:"spinner"})," Loading Radarr library…"]}):m?e.jsx("div",{className:"table-wrapper",children:e.jsxs("table",{className:"responsive-table",children:[e.jsx("thead",{children:n.getHeaderGroups().map(o=>e.jsx("tr",{children:o.headers.map(v=>e.jsx("th",{className:v.column.getCanSort()?"sortable":"",onClick:()=>{const h=v.id;P(h)},children:v.isPlaceholder?null:pe(v.column.columnDef.header,v.getContext())},v.id))},o.id))}),e.jsx("tbody",{children:n.getRowModel().rows.map(o=>{const v=o.original,h=`${v.__instance}-${v.title}-${v.year}`;return e.jsx("tr",{children:o.getVisibleCells().map(x=>e.jsx("td",{children:pe(x.column.columnDef.cell,x.getContext())},x.id))},h)})})]})}):e.jsx("div",{className:"hint",children:"No movies found."}),m>0&&e.jsxs("div",{className:"pagination",children:[e.jsxs("div",{children:["Page ",f+1," of ",R," (",m.toLocaleString()," items · page size"," ",Se,")"]}),e.jsxs("div",{className:"inline",children:[e.jsx("button",{className:"btn",onClick:()=>M(Math.max(0,f-1)),disabled:f===0||d,children:"Prev"}),e.jsx("button",{className:"btn",onClick:()=>M(Math.min(R-1,f+1)),disabled:f>=R-1||d,children:"Next"})]})]})]})}function hs({loading:d,data:c,page:m,totalPages:f,pageSize:R,allMovies:M,onlyMissing:L,reasonFilter:I,onPageChange:p,onRestart:P,lastUpdated:i}){const g=a.useMemo(()=>{let h=M;return L&&(h=h.filter(x=>!x.hasFile)),h},[M,L]),n=a.useMemo(()=>I==="all"?g:I==="none"?g.filter(h=>!h.reason):g.filter(h=>h.reason===I),[g,I]),o=a.useMemo(()=>[{accessorKey:"title",header:"Title",cell:h=>h.getValue()},{accessorKey:"year",header:"Year",size:80},{accessorKey:"monitored",header:"Monitored",cell:h=>h.getValue()?e.jsx("span",{className:"table-badge",children:"Yes"}):e.jsx("span",{children:"No"}),size:100},{accessorKey:"hasFile",header:"Has File",cell:h=>h.getValue()?e.jsx("span",{className:"table-badge",children:"Yes"}):e.jsx("span",{children:"No"}),size:100},{accessorKey:"reason",header:"Reason",cell:h=>{const x=h.getValue();return x?e.jsx("span",{className:"table-badge table-badge-reason",children:x}):e.jsx("span",{className:"hint",children:"—"})},size:120}],[]),v=Le({data:n.slice(m*R,m*R+R),columns:o,getCoreRowModel:Pe(),getSortedRowModel:ns()});return e.jsxs("div",{className:"stack animate-fade-in",children:[e.jsxs("div",{className:"row",style:{justifyContent:"space-between"},children:[e.jsxs("div",{className:"hint",children:[c?.counts?`Available: ${c.counts.available??0} • Monitored: ${c.counts.monitored??0}`:"",i?` (updated ${i})`:""]}),e.jsxs("button",{className:"btn ghost",onClick:P,disabled:d,children:[e.jsx(Je,{src:Ge}),"Restart"]})]}),d?e.jsxs("div",{className:"loading",children:[e.jsx("span",{className:"spinner"})," Loading…"]}):M.length?e.jsx("div",{className:"table-wrapper",children:e.jsxs("table",{className:"responsive-table",children:[e.jsx("thead",{children:v.getHeaderGroups().map(h=>e.jsx("tr",{children:h.headers.map(x=>e.jsx("th",{children:x.isPlaceholder?null:pe(x.column.columnDef.header,x.getContext())},x.id))},h.id))}),e.jsx("tbody",{children:v.getRowModel().rows.map(h=>{const x=h.original,G=`${x.title}-${x.year}`;return e.jsx("tr",{children:h.getVisibleCells().map(W=>e.jsx("td",{children:pe(W.column.columnDef.cell,W.getContext())},W.id))},G)})})]})}):e.jsx("div",{className:"hint",children:"No movies found."}),n.length>R&&e.jsxs("div",{className:"pagination",children:[e.jsxs("div",{children:["Page ",m+1," of ",f," (",n.length.toLocaleString()," items · page size"," ",R,")"]}),e.jsxs("div",{className:"inline",children:[e.jsx("button",{className:"btn",onClick:()=>p(Math.max(0,m-1)),disabled:m===0||d,children:"Prev"}),e.jsx("button",{className:"btn",onClick:()=>p(Math.min(f-1,m+1)),disabled:m>=f-1||d,children:"Next"})]})]})]})}function us({active:d}){const{push:c}=qe(),{value:m,setValue:f,register:R,clearHandler:M}=es(),{liveArr:L,setLiveArr:I}=ss(),[p,P]=a.useState([]),[i,g]=a.useState("aggregate"),[n,o]=a.useState(null),[v,h]=a.useState(0),[x,G]=a.useState(""),[W,ie]=a.useState(!1),[re,X]=a.useState(null),[V,se]=a.useState({}),[l,E]=a.useState(Ye),[y,_]=a.useState(1),D=a.useRef(""),K=a.useRef({}),Y=a.useRef(m),H=a.useRef(!1),[le,ue]=a.useState([]),[ye,oe]=a.useState(!1),[ce,me]=a.useState(0),[q,ve]=a.useState(""),[Re,Ne]=a.useState(null),[ee,xe]=a.useState({key:"__instance",direction:"asc"}),[ae,_e]=a.useState(!1),[te,O]=a.useState("all"),[ke,Q]=a.useState({available:0,monitored:0,missing:0,total:0}),Me=a.useCallback(async()=>{try{const t=await as();t.ready===!1&&!H.current?(H.current=!0,c("Radarr backend is still initialising. Check the logs if this persists.","info")):t.ready&&(H.current=!0);const s=(t.arr||[]).filter(r=>r.type==="radarr");if(P(s),!s.length){g("aggregate"),o(null),ue([]),Q({available:0,monitored:0,missing:0,total:0});return}i===""?g("aggregate"):i!=="aggregate"&&!s.some(r=>r.category===i)&&g(s[0].category)}catch(t){c(t instanceof Error?t.message:"Unable to load Radarr instances","error")}},[c,i]),Ae=a.useCallback(async(t,s,r,u,N)=>{if(u.length)try{const $=[];for(const j of u){const b=await Ve(t,j,r,s),S=b.page??j;if($.push({page:S,movies:b.movies??[]}),D.current!==N)return}if(D.current!==N)return;se(j=>{const b={...j};let S=!1;for(const{page:C,movies:F}of $){const w=j[C]??[];JSON.stringify(w)!==JSON.stringify(F)&&(b[C]=F,S=!0)}return K.current=b,S?b:j})}catch($){c($ instanceof Error?$.message:`Failed to load additional pages for ${t}`,"error")}},[c]),J=a.useCallback(async(t,s,r,u={})=>{const N=u.preloadAll!==!1;(u.showLoading??!0)&&ie(!0);try{const j=`${t}::${r}`,b=D.current!==j;b&&(D.current=j,se(()=>(K.current={},{})));const S=await Ve(t,s,Ye,r);o(S);const C=S.page??s;h(C),G(r);const F=S.page_size??Ye,w=S.total??(S.movies??[]).length,T=Math.max(1,Math.ceil((w||0)/F));E(F),_(T);const k=S.movies??[],ge=b?{}:K.current,he=K.current[C]??[],je=JSON.stringify(he)!==JSON.stringify(k);if((b||je)&&(se(z=>{const we={...b?{}:z,[C]:k};return K.current=we,we}),X(new Date().toLocaleTimeString())),N){const z=[];for(let B=0;B<T;B+=1)B!==C&&(ge[B]||z.push(B));Ae(t,r,F,z,j)}}catch(j){c(j instanceof Error?j.message:`Failed to load ${t} movies`,"error")}finally{ie(!1)}},[c,Ae]),de=a.useCallback(async()=>{if(!p.length){ue([]),Q({available:0,monitored:0,missing:0,total:0});return}oe(!0);try{const t=[];let s=0,r=0;for(const N of p){let $=0,j=!1;const b=N.name||N.category;for(;$<100;){const S=await Ve(N.category,$,Be,"");if(!j){const F=S.counts;F&&(s+=F.available??0,r+=F.monitored??0),j=!0}const C=S.movies??[];if(C.forEach(F=>{t.push({...F,__instance:b})}),!C.length||C.length<Be)break;$+=1}}ue(N=>{const $=JSON.stringify(N),j=JSON.stringify(t);return $===j?N:t});const u={available:s,monitored:r,missing:t.length-s,total:t.length};Q(N=>N.available===u.available&&N.monitored===u.monitored&&N.missing===u.missing&&N.total===u.total?N:u),q!==m&&(me(0),ve(m)),Ne(new Date().toLocaleTimeString())}catch(t){ue([]),Q({available:0,monitored:0,missing:0,total:0}),c(t instanceof Error?t.message:"Failed to load aggregated Radarr data","error")}finally{oe(!1)}},[p,m,c]);a.useEffect(()=>{d&&Me()},[d,Me]),a.useEffect(()=>{if(!d||!i||i==="aggregate")return;K.current={},se({}),_(1),h(0);const t=Y.current;J(i,0,t,{preloadAll:!0,showLoading:!0})},[d,i,J]),a.useEffect(()=>{d&&i==="aggregate"&&de()},[d,i,de]),Ie(()=>{i==="aggregate"&&L&&de()},i==="aggregate"&&L?1e4:null),a.useEffect(()=>{if(!d)return;const t=s=>{i==="aggregate"?(ve(s),me(0)):i&&(h(0),J(i,0,s,{preloadAll:!0,showLoading:!0}))};return R(t),()=>{M(t)}},[d,i,R,M,J]),Ie(()=>{if(i&&i!=="aggregate"){if(Y.current?.trim?.()||"")return;J(i,v,x,{preloadAll:!1,showLoading:!1})}},d&&i&&i!=="aggregate"&&L?1e3:null),a.useEffect(()=>{Y.current=m},[m]),a.useEffect(()=>{i==="aggregate"&&ve(m)},[i,m]);const Z=a.useMemo(()=>{let t=le;if(q){const s=q.toLowerCase();t=t.filter(r=>{const u=(r.title??"").toString().toLowerCase(),N=(r.__instance??"").toLowerCase();return u.includes(s)||N.includes(s)})}return ae&&(t=t.filter(s=>!s.hasFile)),te!=="all"&&(te==="none"?t=t.filter(s=>!s.reason):t=t.filter(s=>s.reason===te)),t},[le,q,ae,te]),ne=a.useMemo(()=>{const t=[...Z],s=(r,u)=>{switch(u){case"__instance":return(r.__instance||"").toLowerCase();case"title":return(r.title||"").toLowerCase();case"year":return r.year??0;case"monitored":return r.monitored?1:0;case"hasFile":return r.hasFile?1:0;default:return""}};return t.sort((r,u)=>{const N=s(r,ee.key),$=s(u,ee.key);let j=0;return typeof N=="number"&&typeof $=="number"?j=N-$:typeof N=="string"&&typeof $=="string"?j=N.localeCompare($):j=String(N).localeCompare(String($)),ee.direction==="asc"?j:-j}),t},[Z,ee]),We=Math.max(1,Math.ceil(ne.length/Se)),fe=ne.slice(ce*Se,ce*Se+Se),De=a.useMemo(()=>{const t=Object.keys(V).map(Number).sort((r,u)=>r-u),s=[];return t.forEach(r=>{V[r]&&s.push(...V[r])}),s},[V]),Ke=a.useCallback(async()=>{if(!(!i||i==="aggregate"))try{await ts(i),c(`Restarted ${i}`,"success")}catch(t){c(t instanceof Error?t.message:`Failed to restart ${i}`,"error")}},[i,c]),Te=a.useCallback(t=>{const s=t.target.value||"aggregate";g(s),s!=="aggregate"&&f("")},[g,f]),Ce=i==="aggregate";return e.jsxs("section",{className:"card",children:[e.jsx("div",{className:"card-header",children:"Radarr"}),e.jsx("div",{className:"card-body",children:e.jsxs("div",{className:"split",children:[e.jsxs("aside",{className:"pane sidebar",children:[e.jsx("button",{className:`btn ${Ce?"active":""}`,onClick:()=>g("aggregate"),children:"All Radarr"}),p.map(t=>e.jsx("button",{className:`btn ghost ${i===t.category?"active":""}`,onClick:()=>{g(t.category),f("")},children:t.name||t.category},t.category))]}),e.jsxs("div",{className:"pane",children:[e.jsxs("div",{className:"field mobile-instance-select",children:[e.jsx("label",{children:"Instance"}),e.jsxs("select",{value:i||"aggregate",onChange:Te,disabled:!p.length,children:[e.jsx("option",{value:"aggregate",children:"All Radarr"}),p.map(t=>e.jsx("option",{value:t.category,children:t.name||t.category},t.category))]})]}),e.jsxs("div",{className:"row",style:{alignItems:"flex-end",gap:"12px",flexWrap:"wrap"},children:[e.jsxs("div",{className:"col field",style:{flex:"1 1 200px"},children:[e.jsx("label",{children:"Search"}),e.jsx("input",{placeholder:"Filter movies",value:m,onChange:t=>f(t.target.value)})]}),e.jsxs("div",{className:"field",style:{flex:"0 0 auto",minWidth:"140px"},children:[e.jsx("label",{children:"Status"}),e.jsxs("select",{onChange:t=>{const s=t.target.value;_e(s==="missing")},value:ae?"missing":"all",children:[e.jsx("option",{value:"all",children:"All Movies"}),e.jsx("option",{value:"missing",children:"Missing Only"})]})]}),e.jsxs("div",{className:"field",style:{flex:"0 0 auto",minWidth:"140px"},children:[e.jsx("label",{children:"Search Reason"}),e.jsxs("select",{onChange:t=>O(t.target.value),value:te,children:[e.jsx("option",{value:"all",children:"All Reasons"}),e.jsx("option",{value:"none",children:"Not Being Searched"}),e.jsx("option",{value:"Missing",children:"Missing"}),e.jsx("option",{value:"Quality",children:"Quality"}),e.jsx("option",{value:"CustomFormat",children:"Custom Format"}),e.jsx("option",{value:"Upgrade",children:"Upgrade"}),e.jsx("option",{value:"Scheduled search",children:"Scheduled Search"})]})]})]}),Ce?e.jsx(gs,{loading:ye,rows:fe,total:ne.length,page:ce,totalPages:We,onPageChange:me,onRefresh:()=>void de(),lastUpdated:Re,sort:ee,onSort:t=>xe(s=>s.key===t?{key:t,direction:s.direction==="asc"?"desc":"asc"}:{key:t,direction:"asc"}),summary:ke}):e.jsx(hs,{loading:W,data:n,page:v,totalPages:y,pageSize:l,allMovies:De,onlyMissing:ae,reasonFilter:te,onPageChange:t=>{h(t),J(i,t,x,{preloadAll:!0})},onRestart:()=>void Ke(),lastUpdated:re})]})]})})]})}const He=25,Fe=50,Xe=200;function ms(d,c){if(!c)return d;const m=[];for(const f of d){const R=f.seasons??{},M={};for(const[L,I]of Object.entries(R)){const p=(I.episodes??[]).filter(P=>!P.hasFile);p.length&&(M[L]={...I,episodes:p})}Object.keys(M).length!==0&&m.push({...f,seasons:M})}return m}function Ee(d,c){return JSON.stringify(ms(d,c))}function xs({active:d}){const{push:c}=qe(),{value:m,setValue:f,register:R,clearHandler:M}=es(),{liveArr:L,setLiveArr:I,groupSonarr:p,setGroupSonarr:P}=ss(),[i,g]=a.useState([]),[n,o]=a.useState("aggregate"),[v,h]=a.useState(null),[x,G]=a.useState(0),[W,ie]=a.useState(""),[re,X]=a.useState(!1),[V,se]=a.useState(null),[l,E]=a.useState({}),y=a.useRef({}),_=a.useRef(null),D=a.useRef(""),[K,Y]=a.useState(He),[H,le]=a.useState(1),[ue,ye]=a.useState(0),oe=a.useRef(m),ce=a.useRef(!1),[me,q]=a.useState([]),[ve,Re]=a.useState(!1),[Ne,ee]=a.useState(0),[xe,ae]=a.useState(""),[_e,te]=a.useState(null),[O,ke]=a.useState(!1),[Q,Me]=a.useState("all"),[Ae,J]=a.useState({available:0,monitored:0,missing:0,total:0}),de=a.useCallback(async()=>{try{const s=await as();s.ready===!1&&!ce.current?(ce.current=!0,c("Sonarr backend is still initialising. Check the logs if this persists.","info")):s.ready&&(ce.current=!0);const r=(s.arr||[]).filter(u=>u.type==="sonarr");if(g(r),!r.length){o("aggregate"),h(null),q([]),J({available:0,monitored:0,missing:0,total:0});return}n===""?o("aggregate"):n!=="aggregate"&&!r.some(u=>u.category===n)&&o(r[0].category)}catch(s){c(s instanceof Error?s.message:"Unable to load Sonarr instances","error")}},[c,n]),Z=a.useCallback(async(s,r,u,N={})=>{const{preloadAll:$=!0,showLoading:j=!0,missingOnly:b}=N,S=b??O;j&&X(!0);try{const C=`${s}::${u}::${S?"missing":"all"}`,F=D.current!==C;F&&(D.current=C,E(()=>(y.current={},{})),ye(0),le(1));const w=await Ue(s,r,He,u,{missingOnly:S}),T=w.page??r,k=w.page_size??He,ge=w.total??(w.series??[]).length,he=Math.max(1,Math.ceil((ge||0)/k)),je=w.series??[],z=F?{}:y.current,B={...z,[T]:je},we=Ee(z[T]??[],S),is=Ee(je,S),Oe=F||we!==is;if(y.current=B,Oe&&E(B),h(A=>{const U=A?.counts??null,be=w.counts??null;return!A||A.total!==w.total||A.page!==w.page||A.page_size!==w.page_size||(U?.available??null)!==(be?.available??null)||(U?.monitored??null)!==(be?.monitored??null)||(U?.missing??null)!==(be?.missing??null)||Oe?(_.current=w,w):A}),G(A=>A===T?A:T),ie(A=>A===u?A:u),Y(A=>A===k?A:k),le(A=>A===he?A:he),ye(A=>A===ge?A:ge),Oe&&se(new Date().toLocaleTimeString()),$){const A=[];for(let U=0;U<he;U+=1)U!==T&&(B[U]||A.push(U));for(const U of A)try{const be=await Ue(s,U,k,u,{missingOnly:S});if(D.current!==C)break;const $e=be.page??U,ze=be.series??[],Qe=y.current,rs=Ee(Qe[$e]??[],S),ls=Ee(ze,S);if(rs===ls){y.current={...Qe,[$e]:ze};continue}E(os=>{const Ze={...os,[$e]:ze};return y.current=Ze,Ze})}catch{break}}}catch(C){c(C instanceof Error?C.message:`Failed to load ${s} series`,"error")}finally{j&&X(!1)}},[c,O]),ne=a.useCallback(async()=>{if(!i.length){q([]),J({available:0,monitored:0,missing:0,total:0});return}console.log(`[Sonarr Aggregate] Starting aggregation for ${i.length} instances`),Re(!0);try{const s=[];let r=0,u=0,N=0;for(const b of i){let S=0,C=!1;const F=b.name||b.category;for(console.log(`[Sonarr Aggregate] Processing instance: ${F}`);S<200;){const w=await Ue(b.category,S,Xe,"",{missingOnly:O});if(console.log(`[Sonarr Aggregate] Response for ${F} page ${S}:`,{total:w.total,page:w.page,page_size:w.page_size,series_count:w.series?.length??0,counts:w.counts}),!C){const k=w.counts;k&&(r+=k.available??0,u+=k.monitored??0,N+=k.missing??0),C=!0}const T=w.series??[];if(console.log(`[Sonarr Aggregate] Instance: ${F}, Page: ${S}, Series count: ${T.length}, Total episodes so far: ${s.length}`),T.forEach(k=>{const ge=k.series?.title||"";Object.entries(k.seasons??{}).forEach(([he,je])=>{(je.episodes??[]).forEach(z=>{s.push({__instance:F,series:ge,season:he,episode:z.episodeNumber??"",title:z.title??"",monitored:!!z.monitored,hasFile:!!z.hasFile,airDate:z.airDateUtc??""})})})}),!T.length||T.length<Xe){console.log(`[Sonarr Aggregate] Breaking pagination for ${F} - series.length=${T.length}`);break}S+=1}}const $=new Set(s.map(b=>`${b.__instance}::${b.series}`)).size;console.log("[Sonarr Aggregate] Aggregation complete:",{totalEpisodes:s.length,uniqueSeries:$,instances:i.length}),q(b=>{const S=JSON.stringify(b),C=JSON.stringify(s);return S===C?(console.log("[Sonarr Aggregate] Data unchanged, skipping update"),b):(console.log(`[Sonarr Aggregate] Data changed, updating from ${b.length} to ${s.length} episodes`),s)});const j={available:r,monitored:u,missing:N,total:s.length};J(b=>b.available===j.available&&b.monitored===j.monitored&&b.missing===j.missing&&b.total===j.total?b:j),xe!==m&&(ee(0),ae(m)),te(new Date().toLocaleTimeString())}catch(s){q([]),J({available:0,monitored:0,missing:0,total:0}),c(s instanceof Error?s.message:"Failed to load aggregated Sonarr data","error")}finally{Re(!1)}},[i,m,c,O]);a.useEffect(()=>{d&&de()},[d,de]),a.useEffect(()=>{if(!d||!n||n==="aggregate")return;G(0);const s=oe.current;Z(n,0,s,{preloadAll:!0,showLoading:!0,missingOnly:O})},[d,n,Z]),a.useEffect(()=>{d&&n==="aggregate"&&ne()},[d,n,ne]),Ie(()=>{n==="aggregate"&&L&&ne()},n==="aggregate"&&L?1e4:null),a.useEffect(()=>{if(!d)return;const s=r=>{n==="aggregate"?(ae(r),ee(0)):n&&(G(0),Z(n,0,r,{preloadAll:!0,showLoading:!0,missingOnly:O}))};return R(s),()=>M(s)},[d,n,R,M,Z,O]),Ie(()=>{if(n&&n!=="aggregate"){if(oe.current?.trim?.()||"")return;Z(n,x,W,{preloadAll:!1,showLoading:!1,missingOnly:O})}},d&&n&&n!=="aggregate"&&L?1e3:null),a.useEffect(()=>{oe.current=m},[m]),a.useEffect(()=>{n==="aggregate"&&ae(m)},[n,m]);const fe=a.useMemo(()=>{let s=me;if(xe){const r=xe.toLowerCase();s=s.filter(u=>u.series.toLowerCase().includes(r)||u.title.toLowerCase().includes(r)||u.__instance.toLowerCase().includes(r))}return Q!=="all"&&(Q==="none"?s=s.filter(r=>!r.reason):s=s.filter(r=>r.reason===Q)),s},[me,xe,Q]),De=Math.max(1,Math.ceil(fe.length/Fe));fe.slice(Ne*Fe,Ne*Fe+Fe);const Ke=l[x]??[],Te=a.useCallback(async()=>{if(!(!n||n==="aggregate"))try{await ts(n),c(`Restarted ${n}`,"success")}catch(s){c(s instanceof Error?s.message:`Failed to restart ${n}`,"error")}},[n,c]),Ce=a.useCallback(s=>{const r=s.target.value||"aggregate";o(r),r!=="aggregate"&&f("")},[o,f]),t=n==="aggregate";return e.jsxs("section",{className:"card",children:[e.jsx("div",{className:"card-header",children:"Sonarr"}),e.jsx("div",{className:"card-body",children:e.jsxs("div",{className:"split",children:[e.jsxs("aside",{className:"pane sidebar",children:[e.jsx("button",{className:`btn ${t?"active":""}`,onClick:()=>o("aggregate"),children:"All Sonarr"}),i.map(s=>e.jsx("button",{className:`btn ghost ${n===s.category?"active":""}`,onClick:()=>{o(s.category),f("")},children:s.name||s.category},s.category))]}),e.jsxs("div",{className:"pane",children:[e.jsxs("div",{className:"field mobile-instance-select",children:[e.jsx("label",{children:"Instance"}),e.jsxs("select",{value:n||"aggregate",onChange:Ce,disabled:!i.length,children:[e.jsx("option",{value:"aggregate",children:"All Sonarr"}),i.map(s=>e.jsx("option",{value:s.category,children:s.name||s.category},s.category))]})]}),e.jsxs("div",{className:"row",style:{alignItems:"flex-end",gap:"12px",flexWrap:"wrap"},children:[e.jsxs("div",{className:"col field",style:{flex:"1 1 200px"},children:[e.jsx("label",{children:"Search"}),e.jsx("input",{placeholder:"Filter series or episodes",value:m,onChange:s=>f(s.target.value)})]}),e.jsxs("div",{className:"field",style:{flex:"0 0 auto",minWidth:"140px"},children:[e.jsx("label",{children:"Status"}),e.jsxs("select",{onChange:s=>{const u=s.target.value==="missing";ke(u),n&&n!=="aggregate"&&Z(n,0,oe.current||"",{preloadAll:!0,showLoading:!0,missingOnly:u})},value:O?"missing":"all",children:[e.jsx("option",{value:"all",children:"All Episodes"}),e.jsx("option",{value:"missing",children:"Missing Only"})]})]}),e.jsxs("div",{className:"field",style:{flex:"0 0 auto",minWidth:"140px"},children:[e.jsx("label",{children:"Search Reason"}),e.jsxs("select",{onChange:s=>Me(s.target.value),value:Q,children:[e.jsx("option",{value:"all",children:"All Reasons"}),e.jsx("option",{value:"none",children:"Not Being Searched"}),e.jsx("option",{value:"Missing",children:"Missing"}),e.jsx("option",{value:"Quality",children:"Quality"}),e.jsx("option",{value:"CustomFormat",children:"Custom Format"}),e.jsx("option",{value:"Upgrade",children:"Upgrade"}),e.jsx("option",{value:"Scheduled search",children:"Scheduled Search"})]})]})]}),t?e.jsx(fs,{loading:ve,rows:fe,total:fe.length,page:Ne,totalPages:De,onPageChange:ee,onRefresh:()=>void ne(),lastUpdated:_e,groupSonarr:p,summary:Ae}):e.jsx(js,{loading:re,counts:v?.counts??null,series:Ke,page:x,pageSize:K,totalPages:H,totalItems:ue,onlyMissing:O,onPageChange:s=>{G(s),Z(n,s,W,{preloadAll:!1,showLoading:!0,missingOnly:O})},onRestart:()=>void Te(),lastUpdated:V,groupSonarr:p})]})]})})]})}function fs({loading:d,rows:c,total:m,page:f,totalPages:R,onPageChange:M,onRefresh:L,lastUpdated:I,groupSonarr:p,summary:P}){const i=a.useMemo(()=>{const l=new Map;c.forEach(y=>{const _=y.__instance,D=y.series,K=String(y.season);l.has(_)||l.set(_,new Map);const Y=l.get(_);Y.has(D)||Y.set(D,new Map);const H=Y.get(D);H.has(K)||H.set(K,[]),H.get(K).push(y)});const E=[];return l.forEach((y,_)=>{y.forEach((D,K)=>{E.push({instance:_,series:K,subRows:Array.from(D.entries()).map(([Y,H])=>({seasonNumber:Y,isSeason:!0,subRows:H.map(le=>({...le,isEpisode:!0}))}))})})}),E},[c]),g=a.useMemo(()=>i.slice(f*50,(f+1)*50),[i,f]),n=a.useMemo(()=>c.slice(f*50,(f+1)*50),[c,f]),o=p?g:n,v=a.useMemo(()=>[{accessorKey:"title",header:"Title",cell:({row:l})=>l.original.isEpisode?l.original.title:l.original.isSeason?`Season ${l.original.seasonNumber}`:l.original.series},{accessorKey:"monitored",header:"Monitored",cell:({row:l})=>{const E=(l.original.isEpisode,l.original.monitored);return e.jsx("span",{className:"table-badge",children:E?"Yes":"No"})}},{accessorKey:"hasFile",header:"Has File",cell:({row:l})=>l.original.isEpisode?e.jsx("span",{className:"table-badge",children:l.original.hasFile?"Yes":"No"}):null},{accessorKey:"airDate",header:"Air Date",cell:({row:l})=>l.original.isEpisode?l.original.airDate||"—":null}],[]),h=a.useMemo(()=>[{accessorKey:"__instance",header:"Instance"},{accessorKey:"series",header:"Series"},{accessorKey:"season",header:"Season"},{accessorKey:"episode",header:"Episode"},{accessorKey:"title",header:"Title"},{accessorKey:"monitored",header:"Monitored",cell:({getValue:l})=>e.jsx("span",{className:"table-badge",children:l()?"Yes":"No"})},{accessorKey:"hasFile",header:"Has File",cell:({getValue:l})=>e.jsx("span",{className:"table-badge",children:l()?"Yes":"No"})},{accessorKey:"airDate",header:"Air Date",cell:({getValue:l})=>l()||"—"}],[]),x=p?v:h,G=Le({data:o,columns:x,getCoreRowModel:Pe(),getExpandedRowModel:cs()}),W=Le({data:o,columns:x,getCoreRowModel:Pe(),getSortedRowModel:ns(),getPaginationRowModel:ds(),state:{pagination:{pageIndex:f,pageSize:50}},manualPagination:!0,pageCount:R}),ie=p?G:W,re=50,X=Math.ceil(p?i.length/re:c.length/re),V=Math.min(f,Math.max(0,X-1)),se=p?`${i.length} series`:c.length.toLocaleString();return e.jsxs("div",{className:"stack animate-fade-in",children:[e.jsxs("div",{className:"row",style:{justifyContent:"space-between"},children:[e.jsxs("div",{className:"hint",children:["Aggregated episodes across all instances"," ",I?`(updated ${I})`:"",e.jsx("br",{}),e.jsx("strong",{children:"Available:"})," ",P.available.toLocaleString(void 0,{maximumFractionDigits:0})," •"," ",e.jsx("strong",{children:"Monitored:"})," ",P.monitored.toLocaleString(void 0,{maximumFractionDigits:0})," •"," ",e.jsx("strong",{children:"Missing:"})," ",P.missing.toLocaleString(void 0,{maximumFractionDigits:0})," •"," ",e.jsx("strong",{children:"Total Episodes:"})," ",P.total.toLocaleString(void 0,{maximumFractionDigits:0})]}),e.jsxs("button",{className:"btn ghost",onClick:L,disabled:d,children:[e.jsx(Je,{src:Ge}),"Refresh"]})]}),d?e.jsxs("div",{className:"loading",children:[e.jsx("span",{className:"spinner"})," Loading Sonarr library…"]}):p?e.jsx("div",{className:"sonarr-hierarchical-view",children:g.map(l=>e.jsxs("details",{className:"series-details",children:[e.jsxs("summary",{className:"series-summary",children:[e.jsx("span",{className:"series-title",children:l.series}),e.jsxs("span",{className:"series-instance",children:["(",l.instance,")"]})]}),e.jsx("div",{className:"series-content",children:l.subRows.map(E=>e.jsxs("details",{className:"season-details",children:[e.jsxs("summary",{className:"season-summary",children:[e.jsxs("span",{className:"season-title",children:["Season ",E.seasonNumber]}),e.jsxs("span",{className:"season-count",children:["(",E.subRows.length," episodes)"]})]}),e.jsx("div",{className:"season-content",children:e.jsx("div",{className:"episodes-table-wrapper",children:e.jsxs("table",{className:"episodes-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Episode"}),e.jsx("th",{children:"Title"}),e.jsx("th",{children:"Monitored"}),e.jsx("th",{children:"Has File"}),e.jsx("th",{children:"Air Date"}),e.jsx("th",{children:"Reason"})]})}),e.jsx("tbody",{children:E.subRows.map(y=>e.jsxs("tr",{children:[e.jsx("td",{children:y.episode}),e.jsx("td",{children:y.title}),e.jsx("td",{children:e.jsx("span",{className:"table-badge",children:y.monitored?"Yes":"No"})}),e.jsx("td",{children:e.jsx("span",{className:"table-badge",children:y.hasFile?"Yes":"No"})}),e.jsx("td",{children:y.airDate||"—"}),e.jsx("td",{children:y.reason?e.jsx("span",{className:"table-badge table-badge-reason",children:y.reason}):e.jsx("span",{className:"hint",children:"—"})})]},`${y.__instance}-${y.series}-${y.season}-${y.episode}`))})]})})})]},`${l.instance}-${l.series}-${E.seasonNumber}`))})]},`${l.instance}-${l.series}`))}):o.length?e.jsx("div",{className:"table-wrapper",children:e.jsxs("table",{className:"responsive-table",children:[e.jsx("thead",{children:e.jsx("tr",{children:ie.getFlatHeaders().map(l=>e.jsxs("th",{className:l.column.getCanSort()?"sortable":"",onClick:l.column.getToggleSortingHandler(),children:[l.isPlaceholder?null:pe(l.column.columnDef.header,l.getContext()),l.column.getCanSort()&&e.jsx("span",{className:"sort-arrow",children:{asc:"▲",desc:"▼"}[l.column.getIsSorted()]??null})]},l.id))})}),e.jsx("tbody",{children:ie.getRowModel().rows.map(l=>{const E=l.original,y=`${E.__instance}-${E.series}-${E.season}-${E.episode}`;return e.jsx("tr",{children:l.getVisibleCells().map(_=>e.jsx("td",{"data-label":_.column.columnDef.header,children:pe(_.column.columnDef.cell,_.getContext())},_.id))},y)})})]})}):e.jsx("div",{className:"hint",children:"No series found."}),o.length>0&&e.jsxs("div",{className:"pagination",children:[e.jsxs("div",{children:["Page ",V+1," of ",X," (",se," items · page size ",re,")"]}),e.jsxs("div",{className:"inline",children:[e.jsx("button",{className:"btn",onClick:()=>M(Math.max(0,V-1)),disabled:V===0||d,children:"Prev"}),e.jsx("button",{className:"btn",onClick:()=>M(Math.min(X-1,V+1)),disabled:V>=X-1||d,children:"Next"})]})]})]})}function js({loading:d,counts:c,series:m,page:f,pageSize:R,totalPages:M,onPageChange:L,groupSonarr:I}){const p=Math.min(f,Math.max(0,M-1)),P=a.useMemo(()=>{const g=[];for(const n of m){const o=n.series?.title||"";Object.entries(n.seasons??{}).forEach(([v,h])=>{(h.episodes??[]).forEach(x=>{g.push({__instance:"Instance",series:o,season:v,episode:x.episodeNumber??"",title:x.title??"",monitored:!!x.monitored,hasFile:!!x.hasFile,airDate:x.airDateUtc??""})})})}return g},[m]),i=a.useMemo(()=>{const g=new Map;return P.forEach(n=>{const o=n.series;g.has(o)||g.set(o,new Map);const v=g.get(o),h=String(n.season);v.has(h)||v.set(h,[]),v.get(h).push(n)}),Array.from(g.entries()).map(([n,o])=>({series:n,subRows:Array.from(o.entries()).map(([v,h])=>({seasonNumber:v,isSeason:!0,subRows:h.map(x=>({...x,isEpisode:!0}))}))}))},[P]);return e.jsxs("div",{className:"stack animate-fade-in",children:[e.jsx("div",{className:"row",style:{justifyContent:"space-between"},children:e.jsx("div",{className:"hint",children:c?e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:"Available:"})," ",c.available.toLocaleString()," •"," ",e.jsx("strong",{children:"Monitored:"})," ",c.monitored.toLocaleString()," •"," ",e.jsx("strong",{children:"Missing:"})," ",c.missing?.toLocaleString()??0]}):"Loading series information..."})}),d?e.jsxs("div",{className:"loading",children:[e.jsx("span",{className:"spinner"})," Loading series…"]}):I?e.jsx("div",{className:"sonarr-hierarchical-view",children:i.map(g=>e.jsxs("details",{className:"series-details",children:[e.jsx("summary",{className:"series-summary",children:e.jsx("span",{className:"series-title",children:g.series})}),e.jsx("div",{className:"series-content",children:g.subRows.map(n=>e.jsxs("details",{className:"season-details",children:[e.jsxs("summary",{className:"season-summary",children:[e.jsxs("span",{className:"season-title",children:["Season ",n.seasonNumber]}),e.jsxs("span",{className:"season-count",children:["(",n.subRows.length," episodes)"]})]}),e.jsx("div",{className:"season-content",children:e.jsx("div",{className:"episodes-table-wrapper",children:e.jsxs("table",{className:"episodes-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Episode"}),e.jsx("th",{children:"Title"}),e.jsx("th",{children:"Monitored"}),e.jsx("th",{children:"Has File"}),e.jsx("th",{children:"Air Date"}),e.jsx("th",{children:"Reason"})]})}),e.jsx("tbody",{children:n.subRows.map(o=>e.jsxs("tr",{children:[e.jsx("td",{children:o.episode}),e.jsx("td",{children:o.title}),e.jsx("td",{children:e.jsx("span",{className:"table-badge",children:o.monitored?"Yes":"No"})}),e.jsx("td",{children:e.jsx("span",{className:"table-badge",children:o.hasFile?"Yes":"No"})}),e.jsx("td",{children:o.airDate||"—"}),e.jsx("td",{children:o.reason?e.jsx("span",{className:"table-badge table-badge-reason",children:o.reason}):e.jsx("span",{className:"hint",children:"—"})})]},`${o.series}-${o.season}-${o.episode}`))})]})})})]},`${g.series}-${n.seasonNumber}`))})]},`${g.series}`))}):P.length?e.jsxs("div",{className:"table-wrapper",children:[e.jsxs("table",{className:"responsive-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Series"}),e.jsx("th",{children:"Season"}),e.jsx("th",{children:"Episode"}),e.jsx("th",{children:"Title"}),e.jsx("th",{children:"Monitored"}),e.jsx("th",{children:"Has File"}),e.jsx("th",{children:"Air Date"}),e.jsx("th",{children:"Reason"})]})}),e.jsx("tbody",{children:P.slice(p*R,p*R+R).map((g,n)=>e.jsxs("tr",{children:[e.jsx("td",{children:g.series}),e.jsx("td",{children:g.season}),e.jsx("td",{children:g.episode}),e.jsx("td",{children:g.title}),e.jsx("td",{children:e.jsx("span",{className:"table-badge",children:g.monitored?"Yes":"No"})}),e.jsx("td",{children:e.jsx("span",{className:"table-badge",children:g.hasFile?"Yes":"No"})}),e.jsx("td",{children:g.airDate||"—"}),e.jsx("td",{children:g.reason?e.jsx("span",{className:"table-badge table-badge-reason",children:g.reason}):e.jsx("span",{className:"hint",children:"—"})})]},`${g.series}-${g.season}-${g.episode}-${n}`))})]}),e.jsxs("div",{className:"pagination",children:[e.jsxs("div",{children:["Page ",p+1," of ",M," (",P.length.toLocaleString()," items · page size ",R,")"]}),e.jsxs("div",{className:"inline",children:[e.jsx("button",{className:"btn",onClick:()=>L(Math.max(0,p-1)),disabled:p===0||d,children:"Prev"}),e.jsx("button",{className:"btn",onClick:()=>L(Math.min(M-1,p+1)),disabled:p>=M-1||d,children:"Next"})]})]})]}):e.jsx("div",{className:"hint",children:"No series found."})]})}function Ss({type:d,active:c}){return d==="radarr"?e.jsx(us,{active:c}):e.jsx(xs,{active:c})}export{Ss as ArrView};
|
|
2
|
+
//# sourceMappingURL=ArrView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArrView.js","sources":["../../../webui/src/pages/RadarrView.tsx","../../../webui/src/pages/SonarrView.tsx","../../../webui/src/pages/ArrView.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type JSX,\n} from \"react\";\nimport {\n getArrList,\n getRadarrMovies,\n restartArr,\n} from \"../api/client\";\nimport {\n useReactTable,\n getCoreRowModel,\n getSortedRowModel,\n getPaginationRowModel,\n flexRender,\n type ColumnDef,\n} from \"@tanstack/react-table\";\nimport type {\n ArrInfo,\n RadarrMovie,\n RadarrMoviesResponse,\n} from \"../api/types\";\nimport { useToast } from \"../context/ToastContext\";\nimport { useSearch } from \"../context/SearchContext\";\nimport { useWebUI } from \"../context/WebUIContext\";\nimport { useInterval } from \"../hooks/useInterval\";\nimport { IconImage } from \"../components/IconImage\";\nimport RefreshIcon from \"../icons/refresh-arrow.svg\";\nimport RestartIcon from \"../icons/refresh-arrow.svg\";\n\ninterface RadarrAggRow extends RadarrMovie {\n __instance: string;\n}\n\ntype RadarrSortKey = \"title\" | \"year\" | \"monitored\" | \"hasFile\";\ntype RadarrAggSortKey = \"__instance\" | RadarrSortKey;\n\nconst RADARR_PAGE_SIZE = 50;\nconst RADARR_AGG_PAGE_SIZE = 50;\nconst RADARR_AGG_FETCH_SIZE = 500;\n\ninterface RadarrAggregateViewProps {\n loading: boolean;\n rows: RadarrAggRow[];\n total: number;\n page: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n onRefresh: () => void;\n lastUpdated: string | null;\n sort: { key: RadarrAggSortKey; direction: \"asc\" | \"desc\" };\n onSort: (key: RadarrAggSortKey) => void;\n summary: { available: number; monitored: number; missing: number; total: number };\n}\n\nfunction RadarrAggregateView({\n loading,\n rows,\n total,\n page,\n totalPages,\n onPageChange,\n onRefresh,\n lastUpdated,\n sort,\n onSort,\n summary,\n}: RadarrAggregateViewProps): JSX.Element {\n const columns = useMemo<ColumnDef<RadarrAggRow>[]>(\n () => [\n {\n accessorKey: \"__instance\",\n header: \"Instance\",\n size: 150,\n },\n {\n accessorKey: \"title\",\n header: \"Title\",\n cell: (info) => info.getValue(),\n },\n {\n accessorKey: \"year\",\n header: \"Year\",\n size: 80,\n },\n {\n accessorKey: \"monitored\",\n header: \"Monitored\",\n cell: (info) =>\n (info.getValue() as boolean) ? <span className=\"table-badge\">Yes</span> : <span>No</span>,\n size: 100,\n },\n {\n accessorKey: \"hasFile\",\n header: \"Has File\",\n cell: (info) =>\n (info.getValue() as boolean) ? <span className=\"table-badge\">Yes</span> : <span>No</span>,\n size: 100,\n },\n {\n accessorKey: \"reason\",\n header: \"Reason\",\n cell: (info) => {\n const reason = info.getValue() as string | null;\n if (!reason) return <span className=\"hint\">—</span>;\n return <span className=\"table-badge table-badge-reason\">{reason}</span>;\n },\n size: 120,\n },\n ],\n []\n );\n\n const table = useReactTable({\n data: rows,\n columns,\n getCoreRowModel: getCoreRowModel(),\n });\n\n return (\n <div className=\"stack animate-fade-in\">\n <div className=\"row\" style={{ justifyContent: \"space-between\" }}>\n <div className=\"hint\">\n Aggregated movies across all instances{\" \"}\n {lastUpdated ? `(updated ${lastUpdated})` : \"\"}\n <br />\n <strong>Available:</strong>{\" \"}\n {summary.available.toLocaleString(undefined, { maximumFractionDigits: 0 })} •{\" \"}\n <strong>Monitored:</strong>{\" \"}\n {summary.monitored.toLocaleString(undefined, { maximumFractionDigits: 0 })} •{\" \"}\n <strong>Missing:</strong>{\" \"}\n {summary.missing.toLocaleString(undefined, { maximumFractionDigits: 0 })} •{\" \"}\n <strong>Total:</strong>{\" \"}\n {summary.total.toLocaleString(undefined, { maximumFractionDigits: 0 })}\n </div>\n <button className=\"btn ghost\" onClick={onRefresh} disabled={loading}>\n <IconImage src={RefreshIcon} />\n Refresh\n </button>\n </div>\n\n {loading ? (\n <div className=\"loading\">\n <span className=\"spinner\" /> Loading Radarr library…\n </div>\n ) : total ? (\n <div className=\"table-wrapper\">\n <table className=\"responsive-table\">\n <thead>\n {table.getHeaderGroups().map((headerGroup) => (\n <tr key={headerGroup.id}>\n {headerGroup.headers.map((header) => (\n <th\n key={header.id}\n className={header.column.getCanSort() ? \"sortable\" : \"\"}\n onClick={() => {\n const sortKey = header.id as RadarrAggSortKey;\n onSort(sortKey);\n }}\n >\n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n </th>\n ))}\n </tr>\n ))}\n </thead>\n <tbody>\n {table.getRowModel().rows.map((row) => {\n const movie = row.original;\n const stableKey = `${movie.__instance}-${movie.title}-${movie.year}`;\n return (\n <tr key={stableKey}>\n {row.getVisibleCells().map((cell) => (\n <td key={cell.id}>\n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext()\n )}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n ) : (\n <div className=\"hint\">No movies found.</div>\n )}\n\n {total > 0 && (\n <div className=\"pagination\">\n <div>\n Page {page + 1} of {totalPages} ({total.toLocaleString()} items · page size{\" \"}\n {RADARR_AGG_PAGE_SIZE})\n </div>\n <div className=\"inline\">\n <button\n className=\"btn\"\n onClick={() => onPageChange(Math.max(0, page - 1))}\n disabled={page === 0 || loading}\n >\n Prev\n </button>\n <button\n className=\"btn\"\n onClick={() => onPageChange(Math.min(totalPages - 1, page + 1))}\n disabled={page >= totalPages - 1 || loading}\n >\n Next\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n\ninterface RadarrInstanceViewProps {\n loading: boolean;\n data: RadarrMoviesResponse | null;\n page: number;\n totalPages: number;\n pageSize: number;\n allMovies: RadarrMovie[];\n onlyMissing: boolean;\n reasonFilter: string;\n onPageChange: (page: number) => void;\n onRestart: () => void;\n lastUpdated: string | null;\n}\n\nfunction RadarrInstanceView({\n loading,\n data,\n page,\n totalPages,\n pageSize,\n allMovies,\n onlyMissing,\n reasonFilter,\n onPageChange,\n onRestart,\n lastUpdated,\n}: RadarrInstanceViewProps): JSX.Element {\n const filteredMovies = useMemo(() => {\n let movies = allMovies;\n if (onlyMissing) {\n movies = movies.filter((m) => !m.hasFile);\n }\n return movies;\n }, [allMovies, onlyMissing]);\n\n const reasonFilteredMovies = useMemo(() => {\n if (reasonFilter === \"all\") return filteredMovies;\n if (reasonFilter === \"none\") {\n return filteredMovies.filter((m) => !m.reason);\n }\n return filteredMovies.filter((m) => m.reason === reasonFilter);\n }, [filteredMovies, reasonFilter]);\n\n const columns = useMemo<ColumnDef<RadarrMovie>[]>(\n () => [\n {\n accessorKey: \"title\",\n header: \"Title\",\n cell: (info) => info.getValue(),\n },\n {\n accessorKey: \"year\",\n header: \"Year\",\n size: 80,\n },\n {\n accessorKey: \"monitored\",\n header: \"Monitored\",\n cell: (info) =>\n (info.getValue() as boolean) ? <span className=\"table-badge\">Yes</span> : <span>No</span>,\n size: 100,\n },\n {\n accessorKey: \"hasFile\",\n header: \"Has File\",\n cell: (info) =>\n (info.getValue() as boolean) ? <span className=\"table-badge\">Yes</span> : <span>No</span>,\n size: 100,\n },\n {\n accessorKey: \"reason\",\n header: \"Reason\",\n cell: (info) => {\n const reason = info.getValue() as string | null;\n if (!reason) return <span className=\"hint\">—</span>;\n return <span className=\"table-badge table-badge-reason\">{reason}</span>;\n },\n size: 120,\n },\n ],\n []\n );\n\n const table = useReactTable({\n data: reasonFilteredMovies.slice(page * pageSize, page * pageSize + pageSize),\n columns,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n });\n\n return (\n <div className=\"stack animate-fade-in\">\n <div className=\"row\" style={{ justifyContent: \"space-between\" }}>\n <div className=\"hint\">\n {data?.counts\n ? `Available: ${data.counts.available ?? 0} • Monitored: ${\n data.counts.monitored ?? 0\n }`\n : \"\"}\n {lastUpdated ? ` (updated ${lastUpdated})` : \"\"}\n </div>\n <button className=\"btn ghost\" onClick={onRestart} disabled={loading}>\n <IconImage src={RestartIcon} />\n Restart\n </button>\n </div>\n\n {loading ? (\n <div className=\"loading\">\n <span className=\"spinner\" /> Loading…\n </div>\n ) : allMovies.length ? (\n <div className=\"table-wrapper\">\n <table className=\"responsive-table\">\n <thead>\n {table.getHeaderGroups().map((headerGroup) => (\n <tr key={headerGroup.id}>\n {headerGroup.headers.map((header) => (\n <th key={header.id}>\n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n </th>\n ))}\n </tr>\n ))}\n </thead>\n <tbody>\n {table.getRowModel().rows.map((row) => {\n const movie = row.original;\n const stableKey = `${movie.title}-${movie.year}`;\n return (\n <tr key={stableKey}>\n {row.getVisibleCells().map((cell) => (\n <td key={cell.id}>\n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext()\n )}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n ) : (\n <div className=\"hint\">No movies found.</div>\n )}\n\n {reasonFilteredMovies.length > pageSize && (\n <div className=\"pagination\">\n <div>\n Page {page + 1} of {totalPages} ({reasonFilteredMovies.length.toLocaleString()} items · page size{\" \"}\n {pageSize})\n </div>\n <div className=\"inline\">\n <button\n className=\"btn\"\n onClick={() => onPageChange(Math.max(0, page - 1))}\n disabled={page === 0 || loading}\n >\n Prev\n </button>\n <button\n className=\"btn\"\n onClick={() => onPageChange(Math.min(totalPages - 1, page + 1))}\n disabled={page >= totalPages - 1 || loading}\n >\n Next\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport function RadarrView({ active }: { active: boolean }): JSX.Element {\n const { push } = useToast();\n const {\n value: globalSearch,\n setValue: setGlobalSearch,\n register,\n clearHandler,\n } = useSearch();\n const { liveArr, setLiveArr } = useWebUI();\n\n const [instances, setInstances] = useState<ArrInfo[]>([]);\n const [selection, setSelection] = useState<string | \"aggregate\">(\"aggregate\");\n const [instanceData, setInstanceData] = useState<RadarrMoviesResponse | null>(null);\n const [instancePage, setInstancePage] = useState(0);\n const [instanceQuery, setInstanceQuery] = useState(\"\");\n const [instanceLoading, setInstanceLoading] = useState(false);\n const [lastUpdated, setLastUpdated] = useState<string | null>(null);\n const [instancePages, setInstancePages] = useState<Record<number, RadarrMovie[]>>({});\n const [instancePageSize, setInstancePageSize] = useState(RADARR_PAGE_SIZE);\n const [instanceTotalPages, setInstanceTotalPages] = useState(1);\n const instanceKeyRef = useRef<string>(\"\");\n const instancePagesRef = useRef<Record<number, RadarrMovie[]>>({});\n const globalSearchRef = useRef(globalSearch);\n const backendReadyWarnedRef = useRef(false);\n\n const [aggRows, setAggRows] = useState<RadarrAggRow[]>([]);\n const [aggLoading, setAggLoading] = useState(false);\n const [aggPage, setAggPage] = useState(0);\n const [aggFilter, setAggFilter] = useState(\"\");\n const [aggUpdated, setAggUpdated] = useState<string | null>(null);\n const [aggSort, setAggSort] = useState<{\n key: RadarrAggSortKey;\n direction: \"asc\" | \"desc\";\n }>({ key: \"__instance\", direction: \"asc\" });\n const [onlyMissing, setOnlyMissing] = useState(false);\n const [reasonFilter, setReasonFilter] = useState<string>(\"all\");\n const [aggSummary, setAggSummary] = useState<{\n available: number;\n monitored: number;\n missing: number;\n total: number;\n }>({ available: 0, monitored: 0, missing: 0, total: 0 });\n\n const loadInstances = useCallback(async () => {\n try {\n const data = await getArrList();\n if (data.ready === false && !backendReadyWarnedRef.current) {\n backendReadyWarnedRef.current = true;\n push(\"Radarr backend is still initialising. Check the logs if this persists.\", \"info\");\n } else if (data.ready) {\n backendReadyWarnedRef.current = true;\n }\n const filtered = (data.arr || []).filter((arr) => arr.type === \"radarr\");\n setInstances(filtered);\n if (!filtered.length) {\n setSelection(\"aggregate\");\n setInstanceData(null);\n setAggRows([]);\n setAggSummary({ available: 0, monitored: 0, missing: 0, total: 0 });\n return;\n }\n if (selection === \"\") {\n setSelection(\"aggregate\");\n } else if (\n selection !== \"aggregate\" &&\n !filtered.some((arr) => arr.category === selection)\n ) {\n setSelection(filtered[0].category);\n }\n } catch (error) {\n push(\n error instanceof Error\n ? error.message\n : \"Unable to load Radarr instances\",\n \"error\"\n );\n }\n }, [push, selection]);\n\n const preloadRemainingPages = useCallback(\n async (\n category: string,\n query: string,\n pageSize: number,\n pages: number[],\n key: string\n ) => {\n if (!pages.length) return;\n try {\n const results: { page: number; movies: RadarrMovie[] }[] = [];\n for (const pg of pages) {\n const res = await getRadarrMovies(category, pg, pageSize, query);\n const resolved = res.page ?? pg;\n results.push({ page: resolved, movies: res.movies ?? [] });\n if (instanceKeyRef.current !== key) {\n return;\n }\n }\n if (instanceKeyRef.current !== key) return;\n\n // Smart diffing: only update pages that actually changed\n setInstancePages((prev) => {\n const next = { ...prev };\n let hasChanges = false;\n for (const { page, movies } of results) {\n const existingMovies = prev[page] ?? [];\n if (JSON.stringify(existingMovies) !== JSON.stringify(movies)) {\n next[page] = movies;\n hasChanges = true;\n }\n }\n instancePagesRef.current = next;\n return hasChanges ? next : prev;\n });\n } catch (error) {\n push(\n error instanceof Error\n ? error.message\n : `Failed to load additional pages for ${category}`,\n \"error\"\n );\n }\n },\n [push]\n );\n\n const fetchInstance = useCallback(\n async (\n category: string,\n page: number,\n query: string,\n options: { preloadAll?: boolean; showLoading?: boolean } = {}\n ) => {\n const preloadAll = options.preloadAll !== false;\n const showLoading = options.showLoading ?? true;\n if (showLoading) {\n setInstanceLoading(true);\n }\n try {\n const key = `${category}::${query}`;\n const keyChanged = instanceKeyRef.current !== key;\n if (keyChanged) {\n instanceKeyRef.current = key;\n setInstancePages(() => {\n instancePagesRef.current = {};\n return {};\n });\n }\n const response = await getRadarrMovies(\n category,\n page,\n RADARR_PAGE_SIZE,\n query\n );\n setInstanceData(response);\n const resolvedPage = response.page ?? page;\n setInstancePage(resolvedPage);\n setInstanceQuery(query);\n const pageSize = response.page_size ?? RADARR_PAGE_SIZE;\n const totalItems = response.total ?? (response.movies ?? []).length;\n const totalPages = Math.max(1, Math.ceil((totalItems || 0) / pageSize));\n setInstancePageSize(pageSize);\n setInstanceTotalPages(totalPages);\n const movies = response.movies ?? [];\n const existingPages = keyChanged ? {} : instancePagesRef.current;\n\n // Smart diffing: only update if data actually changed\n const existingMovies = instancePagesRef.current[resolvedPage] ?? [];\n const moviesChanged = JSON.stringify(existingMovies) !== JSON.stringify(movies);\n\n if (keyChanged || moviesChanged) {\n setInstancePages((prev) => {\n const base = keyChanged ? {} : prev;\n const next = { ...base, [resolvedPage]: movies };\n instancePagesRef.current = next;\n return next;\n });\n setLastUpdated(new Date().toLocaleTimeString());\n }\n\n if (preloadAll) {\n const pagesToFetch: number[] = [];\n for (let i = 0; i < totalPages; i += 1) {\n if (i === resolvedPage) continue;\n if (!existingPages[i]) {\n pagesToFetch.push(i);\n }\n }\n void preloadRemainingPages(\n category,\n query,\n pageSize,\n pagesToFetch,\n key\n );\n }\n } catch (error) {\n push(\n error instanceof Error\n ? error.message\n : `Failed to load ${category} movies`,\n \"error\"\n );\n } finally {\n setInstanceLoading(false);\n }\n },\n [push, preloadRemainingPages]\n );\n\n const loadAggregate = useCallback(async () => {\n if (!instances.length) {\n setAggRows([]);\n setAggSummary({ available: 0, monitored: 0, missing: 0, total: 0 });\n return;\n }\n setAggLoading(true);\n try {\n const aggregated: RadarrAggRow[] = [];\n let totalAvailable = 0;\n let totalMonitored = 0;\n for (const inst of instances) {\n let page = 0;\n let counted = false;\n const label = inst.name || inst.category;\n while (page < 100) {\n const res = await getRadarrMovies(\n inst.category,\n page,\n RADARR_AGG_FETCH_SIZE,\n \"\"\n );\n if (!counted) {\n const counts = res.counts;\n if (counts) {\n totalAvailable += counts.available ?? 0;\n totalMonitored += counts.monitored ?? 0;\n }\n counted = true;\n }\n const movies = res.movies ?? [];\n movies.forEach((movie) => {\n aggregated.push({ ...movie, __instance: label });\n });\n if (!movies.length || movies.length < RADARR_AGG_FETCH_SIZE) break;\n page += 1;\n }\n }\n\n // Smart diffing: only update if data actually changed\n setAggRows((prev) => {\n const prevJson = JSON.stringify(prev);\n const nextJson = JSON.stringify(aggregated);\n if (prevJson === nextJson) {\n return prev;\n }\n return aggregated;\n });\n\n const newSummary = {\n available: totalAvailable,\n monitored: totalMonitored,\n missing: aggregated.length - totalAvailable,\n total: aggregated.length,\n };\n\n setAggSummary((prev) => {\n if (\n prev.available === newSummary.available &&\n prev.monitored === newSummary.monitored &&\n prev.missing === newSummary.missing &&\n prev.total === newSummary.total\n ) {\n return prev;\n }\n return newSummary;\n });\n\n // Only reset page if filter changed, not on refresh\n if (aggFilter !== globalSearch) {\n setAggPage(0);\n setAggFilter(globalSearch);\n }\n setAggUpdated(new Date().toLocaleTimeString());\n } catch (error) {\n setAggRows([]);\n setAggSummary({ available: 0, monitored: 0, missing: 0, total: 0 });\n push(\n error instanceof Error\n ? error.message\n : \"Failed to load aggregated Radarr data\",\n \"error\"\n );\n } finally {\n setAggLoading(false);\n }\n }, [instances, globalSearch, push]);\n\n // LiveArr is now loaded via WebUIContext, no need to load config here\n\n useEffect(() => {\n if (!active) return;\n void loadInstances();\n }, [active, loadInstances]);\n\n useEffect(() => {\n if (!active) return;\n if (!selection || selection === \"aggregate\") return;\n instancePagesRef.current = {};\n setInstancePages({});\n setInstanceTotalPages(1);\n setInstancePage(0);\n const query = globalSearchRef.current;\n void fetchInstance(selection, 0, query, {\n preloadAll: true,\n showLoading: true,\n });\n }, [active, selection, fetchInstance]); // Removed onlyMissing to prevent refresh\n\n useEffect(() => {\n if (!active) return;\n if (selection !== \"aggregate\") return;\n void loadAggregate();\n }, [active, selection, loadAggregate]);\n\n useInterval(() => {\n if (selection === \"aggregate\" && liveArr) {\n void loadAggregate();\n }\n }, selection === \"aggregate\" && liveArr ? 10000 : null);\n\n useEffect(() => {\n if (!active) return;\n const handler = (term: string) => {\n if (selection === \"aggregate\") {\n setAggFilter(term);\n setAggPage(0);\n } else if (selection) {\n setInstancePage(0);\n void fetchInstance(selection, 0, term, {\n preloadAll: true,\n showLoading: true,\n });\n }\n };\n register(handler);\n return () => {\n clearHandler(handler);\n };\n }, [active, selection, register, clearHandler, fetchInstance]);\n\n useInterval(\n () => {\n if (selection && selection !== \"aggregate\") {\n const activeFilter = globalSearchRef.current?.trim?.() || \"\";\n if (activeFilter) {\n return;\n }\n void fetchInstance(selection, instancePage, instanceQuery, {\n preloadAll: false,\n showLoading: false,\n });\n }\n },\n active && selection && selection !== \"aggregate\" && liveArr ? 1000 : null\n );\n\n // Removed: Don't reset page when filter changes - preserve scroll position\n\n useEffect(() => {\n globalSearchRef.current = globalSearch;\n }, [globalSearch]);\n\n useEffect(() => {\n if (selection === \"aggregate\") {\n setAggFilter(globalSearch);\n }\n }, [selection, globalSearch]);\n\n const filteredAggRows = useMemo(() => {\n let rows = aggRows;\n if (aggFilter) {\n const q = aggFilter.toLowerCase();\n rows = rows.filter((row) => {\n const title = (row.title ?? \"\").toString().toLowerCase();\n const instance = (row.__instance ?? \"\").toLowerCase();\n return title.includes(q) || instance.includes(q);\n });\n }\n if (onlyMissing) {\n rows = rows.filter((row) => !row.hasFile);\n }\n if (reasonFilter !== \"all\") {\n if (reasonFilter === \"none\") {\n rows = rows.filter((row) => !row.reason);\n } else {\n rows = rows.filter((row) => row.reason === reasonFilter);\n }\n }\n return rows;\n }, [aggRows, aggFilter, onlyMissing, reasonFilter]);\n\n const sortedAggRows = useMemo(() => {\n const list = [...filteredAggRows];\n const getValue = (row: RadarrAggRow, key: RadarrAggSortKey) => {\n switch (key) {\n case \"__instance\":\n return (row.__instance || \"\").toLowerCase();\n case \"title\":\n return (row.title || \"\").toLowerCase();\n case \"year\":\n return row.year ?? 0;\n case \"monitored\":\n return row.monitored ? 1 : 0;\n case \"hasFile\":\n return row.hasFile ? 1 : 0;\n default:\n return \"\";\n }\n };\n list.sort((a, b) => {\n const valueA = getValue(a, aggSort.key);\n const valueB = getValue(b, aggSort.key);\n let comparison = 0;\n if (typeof valueA === \"number\" && typeof valueB === \"number\") {\n comparison = valueA - valueB;\n } else if (typeof valueA === \"string\" && typeof valueB === \"string\") {\n comparison = valueA.localeCompare(valueB);\n } else {\n comparison = String(valueA).localeCompare(String(valueB));\n }\n return aggSort.direction === \"asc\" ? comparison : -comparison;\n });\n return list;\n }, [filteredAggRows, aggSort]);\n\n const aggPages = Math.max(\n 1,\n Math.ceil(sortedAggRows.length / RADARR_AGG_PAGE_SIZE)\n );\n const aggPageRows = sortedAggRows.slice(\n aggPage * RADARR_AGG_PAGE_SIZE,\n aggPage * RADARR_AGG_PAGE_SIZE + RADARR_AGG_PAGE_SIZE\n );\n\n const allInstanceMovies = useMemo(() => {\n const pages = Object.keys(instancePages)\n .map(Number)\n .sort((a, b) => a - b);\n const rows: RadarrMovie[] = [];\n pages.forEach((pg) => {\n if (instancePages[pg]) {\n rows.push(...instancePages[pg]);\n }\n });\n return rows;\n }, [instancePages]);\n\n const handleRestart = useCallback(async () => {\n if (!selection || selection === \"aggregate\") return;\n try {\n await restartArr(selection);\n push(`Restarted ${selection}`, \"success\");\n } catch (error) {\n push(\n error instanceof Error ? error.message : `Failed to restart ${selection}`,\n \"error\"\n );\n }\n }, [selection, push]);\n\n const handleInstanceSelection = useCallback(\n (event: ChangeEvent<HTMLSelectElement>) => {\n const next = (event.target.value || \"aggregate\") as string | \"aggregate\";\n setSelection(next);\n if (next !== \"aggregate\") {\n setGlobalSearch(\"\");\n }\n },\n [setSelection, setGlobalSearch]\n );\n\n const isAggregate = selection === \"aggregate\";\n\n return (\n <section className=\"card\">\n <div className=\"card-header\">Radarr</div>\n <div className=\"card-body\">\n <div className=\"split\">\n <aside className=\"pane sidebar\">\n <button\n className={`btn ${isAggregate ? \"active\" : \"\"}`}\n onClick={() => setSelection(\"aggregate\")}\n >\n All Radarr\n </button>\n {instances.map((inst) => (\n <button\n key={inst.category}\n className={`btn ghost ${\n selection === inst.category ? \"active\" : \"\"\n }`}\n onClick={() => {\n setSelection(inst.category);\n setGlobalSearch(\"\");\n }}\n >\n {inst.name || inst.category}\n </button>\n ))}\n </aside>\n <div className=\"pane\">\n <div className=\"field mobile-instance-select\">\n <label>Instance</label>\n <select\n value={selection || \"aggregate\"}\n onChange={handleInstanceSelection}\n disabled={!instances.length}\n >\n <option value=\"aggregate\">All Radarr</option>\n {instances.map((inst) => (\n <option key={inst.category} value={inst.category}>\n {inst.name || inst.category}\n </option>\n ))}\n </select>\n </div>\n <div className=\"row\" style={{ alignItems: \"flex-end\", gap: \"12px\", flexWrap: \"wrap\" }}>\n <div className=\"col field\" style={{ flex: \"1 1 200px\" }}>\n <label>Search</label>\n <input\n placeholder=\"Filter movies\"\n value={globalSearch}\n onChange={(event) => setGlobalSearch(event.target.value)}\n />\n </div>\n <div className=\"field\" style={{ flex: \"0 0 auto\", minWidth: \"140px\" }}>\n <label>Status</label>\n <select\n onChange={(event) => {\n const value = event.target.value;\n setOnlyMissing(value === \"missing\");\n }}\n value={onlyMissing ? \"missing\" : \"all\"}\n >\n <option value=\"all\">All Movies</option>\n <option value=\"missing\">Missing Only</option>\n </select>\n </div>\n <div className=\"field\" style={{ flex: \"0 0 auto\", minWidth: \"140px\" }}>\n <label>Search Reason</label>\n <select\n onChange={(event) => setReasonFilter(event.target.value)}\n value={reasonFilter}\n >\n <option value=\"all\">All Reasons</option>\n <option value=\"none\">Not Being Searched</option>\n <option value=\"Missing\">Missing</option>\n <option value=\"Quality\">Quality</option>\n <option value=\"CustomFormat\">Custom Format</option>\n <option value=\"Upgrade\">Upgrade</option>\n <option value=\"Scheduled search\">Scheduled Search</option>\n </select>\n </div>\n </div>\n\n {isAggregate ? (\n <RadarrAggregateView\n loading={aggLoading}\n rows={aggPageRows}\n total={sortedAggRows.length}\n page={aggPage}\n totalPages={aggPages}\n onPageChange={setAggPage}\n onRefresh={() => void loadAggregate()}\n lastUpdated={aggUpdated}\n sort={aggSort}\n onSort={(key) =>\n setAggSort((prev) =>\n prev.key === key\n ? {\n key,\n direction:\n prev.direction === \"asc\" ? \"desc\" : \"asc\",\n }\n : { key, direction: \"asc\" }\n )\n }\n summary={aggSummary}\n />\n ) : (\n <RadarrInstanceView\n loading={instanceLoading}\n data={instanceData}\n page={instancePage}\n totalPages={instanceTotalPages}\n pageSize={instancePageSize}\n allMovies={allInstanceMovies}\n onlyMissing={onlyMissing}\n reasonFilter={reasonFilter}\n onPageChange={(page) => {\n setInstancePage(page);\n void fetchInstance(selection as string, page, instanceQuery, {\n preloadAll: true,\n });\n }}\n onRestart={() => void handleRestart()}\n lastUpdated={lastUpdated}\n />\n )}\n </div>\n </div>\n </div>\n </section>\n );\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type JSX,\n} from \"react\";\nimport {\n getArrList,\n getSonarrSeries,\n restartArr,\n} from \"../api/client\";\nimport {\n useReactTable,\n getCoreRowModel,\n getSortedRowModel,\n getPaginationRowModel,\n getExpandedRowModel,\n flexRender,\n type ColumnDef,\n} from \"@tanstack/react-table\";\nimport type {\n ArrInfo,\n SonarrEpisode,\n SonarrSeriesEntry,\n SonarrSeriesResponse,\n SonarrSeason,\n} from \"../api/types\";\nimport { useToast } from \"../context/ToastContext\";\nimport { useSearch } from \"../context/SearchContext\";\nimport { useWebUI } from \"../context/WebUIContext\";\nimport { useInterval } from \"../hooks/useInterval\";\nimport { IconImage } from \"../components/IconImage\";\nimport RefreshIcon from \"../icons/refresh-arrow.svg\";\n\ninterface SonarrViewProps {\n active: boolean;\n}\n\ninterface SonarrAggRow {\n __instance: string;\n series: string;\n season: number | string;\n episode: number | string;\n title: string;\n monitored: boolean;\n hasFile: boolean;\n airDate: string;\n reason?: string | null;\n}\n\nconst SONARR_PAGE_SIZE = 25;\nconst SONARR_AGG_PAGE_SIZE = 50;\nconst SONARR_AGG_FETCH_SIZE = 200;\n\nfunction filterSeriesEntriesForMissing(seriesEntries: SonarrSeriesEntry[], onlyMissing: boolean): SonarrSeriesEntry[] {\n if (!onlyMissing) return seriesEntries;\n const result: SonarrSeriesEntry[] = [];\n for (const entry of seriesEntries) {\n const seasons = entry.seasons ?? {};\n const filteredSeasons: Record<string, SonarrSeason> = {};\n for (const [seasonNumber, season] of Object.entries(seasons)) {\n const episodes = (season.episodes ?? []).filter((episode) => !episode.hasFile);\n if (!episodes.length) continue;\n filteredSeasons[seasonNumber] = { ...season, episodes };\n }\n if (Object.keys(filteredSeasons).length === 0) continue;\n result.push({\n ...entry,\n seasons: filteredSeasons,\n });\n }\n return result;\n}\n\nfunction createFilteredSignature(seriesEntries: SonarrSeriesEntry[], onlyMissing: boolean): string {\n return JSON.stringify(filterSeriesEntriesForMissing(seriesEntries, onlyMissing));\n}\n\nexport function SonarrView({ active }: SonarrViewProps): JSX.Element {\n const { push } = useToast();\n const {\n value: globalSearch,\n setValue: setGlobalSearch,\n register,\n clearHandler,\n } = useSearch();\n const { liveArr, setLiveArr, groupSonarr, setGroupSonarr } = useWebUI();\n\n const [instances, setInstances] = useState<ArrInfo[]>([]);\n const [selection, setSelection] = useState<string | \"aggregate\">(\"aggregate\");\n const [instanceData, setInstanceData] =\n useState<SonarrSeriesResponse | null>(null);\n const [instancePage, setInstancePage] = useState(0);\n const [instanceQuery, setInstanceQuery] = useState(\"\");\n const [instanceLoading, setInstanceLoading] = useState(false);\n const [lastUpdated, setLastUpdated] = useState<string | null>(null);\n const [instancePages, setInstancePages] = useState<\n Record<number, SonarrSeriesEntry[]>\n >({});\n const instancePagesRef = useRef<Record<number, SonarrSeriesEntry[]>>({});\n const instanceDataRef = useRef<SonarrSeriesResponse | null>(null);\n const instanceKeyRef = useRef<string>(\"\");\n const [instancePageSize, setInstancePageSize] = useState(SONARR_PAGE_SIZE);\n const [instanceTotalPages, setInstanceTotalPages] = useState(1);\n const [instanceTotalItems, setInstanceTotalItems] = useState(0);\n const globalSearchRef = useRef(globalSearch);\n const backendReadyWarnedRef = useRef(false);\n\n const [aggRows, setAggRows] = useState<SonarrAggRow[]>([]);\n const [aggLoading, setAggLoading] = useState(false);\n const [aggPage, setAggPage] = useState(0);\n const [aggFilter, setAggFilter] = useState(\"\");\n const [aggUpdated, setAggUpdated] = useState<string | null>(null);\n\n const [onlyMissing, setOnlyMissing] = useState(false);\n const [reasonFilter, setReasonFilter] = useState<string>(\"all\");\n const [aggSummary, setAggSummary] = useState<{\n available: number;\n monitored: number;\n missing: number;\n total: number;\n }>({ available: 0, monitored: 0, missing: 0, total: 0 });\n\n // LiveArr and GroupSonarr are now loaded via WebUIContext, no need to load config here\n\n const loadInstances = useCallback(async () => {\n try {\n const data = await getArrList();\n if (data.ready === false && !backendReadyWarnedRef.current) {\n backendReadyWarnedRef.current = true;\n push(\"Sonarr backend is still initialising. Check the logs if this persists.\", \"info\");\n } else if (data.ready) {\n backendReadyWarnedRef.current = true;\n }\n const filtered = (data.arr || []).filter((arr) => arr.type === \"sonarr\");\n setInstances(filtered);\n if (!filtered.length) {\n setSelection(\"aggregate\");\n setInstanceData(null);\n setAggRows([]);\n setAggSummary({ available: 0, monitored: 0, missing: 0, total: 0 });\n return;\n }\n if (selection === \"\") {\n setSelection(\"aggregate\");\n } else if (\n selection !== \"aggregate\" &&\n !filtered.some((arr) => arr.category === selection)\n ) {\n setSelection(filtered[0].category);\n }\n } catch (error) {\n push(\n error instanceof Error\n ? error.message\n : \"Unable to load Sonarr instances\",\n \"error\"\n );\n }\n }, [push, selection]);\n\n const fetchInstance = useCallback(\n async (\n category: string,\n page: number,\n query: string,\n options: { preloadAll?: boolean; showLoading?: boolean; missingOnly?: boolean } = {}\n ) => {\n const { preloadAll = true, showLoading = true, missingOnly } = options;\n const useMissing = missingOnly ?? onlyMissing;\n if (showLoading) {\n setInstanceLoading(true);\n }\n try {\n const key = `${category}::${query}::${useMissing ? \"missing\" : \"all\"}`;\n const keyChanged = instanceKeyRef.current !== key;\n if (keyChanged) {\n instanceKeyRef.current = key;\n setInstancePages(() => {\n instancePagesRef.current = {};\n return {};\n });\n setInstanceTotalItems(0);\n setInstanceTotalPages(1);\n }\n const response = await getSonarrSeries(\n category,\n page,\n SONARR_PAGE_SIZE,\n query,\n { missingOnly: useMissing }\n );\n const resolvedPage = response.page ?? page;\n const pageSize = response.page_size ?? SONARR_PAGE_SIZE;\n const totalItems = response.total ?? (response.series ?? []).length;\n const totalPages = Math.max(1, Math.ceil((totalItems || 0) / pageSize));\n const series = response.series ?? [];\n\n const prevPages = keyChanged ? {} : instancePagesRef.current;\n const nextPages = { ...prevPages, [resolvedPage]: series };\n const prevSignature = createFilteredSignature(prevPages[resolvedPage] ?? [], useMissing);\n const nextSignature = createFilteredSignature(series, useMissing);\n const shouldUpdateCurrentPage = keyChanged || prevSignature !== nextSignature;\n\n instancePagesRef.current = nextPages;\n if (shouldUpdateCurrentPage) {\n setInstancePages(nextPages);\n }\n\n setInstanceData((prev) => {\n const prevCounts = prev?.counts ?? null;\n const nextCounts = response.counts ?? null;\n const countsChanged =\n !prev ||\n prev.total !== response.total ||\n prev.page !== response.page ||\n prev.page_size !== response.page_size ||\n (prevCounts?.available ?? null) !== (nextCounts?.available ?? null) ||\n (prevCounts?.monitored ?? null) !== (nextCounts?.monitored ?? null) ||\n (prevCounts?.missing ?? null) !== (nextCounts?.missing ?? null);\n if (countsChanged || shouldUpdateCurrentPage) {\n instanceDataRef.current = response;\n return response;\n }\n return prev;\n });\n\n setInstancePage((prev) => (prev === resolvedPage ? prev : resolvedPage));\n setInstanceQuery((prev) => (prev === query ? prev : query));\n setInstancePageSize((prev) => (prev === pageSize ? prev : pageSize));\n setInstanceTotalPages((prev) => (prev === totalPages ? prev : totalPages));\n setInstanceTotalItems((prev) => (prev === totalItems ? prev : totalItems));\n\n if (shouldUpdateCurrentPage) {\n setLastUpdated(new Date().toLocaleTimeString());\n }\n\n if (preloadAll) {\n const pagesToFetch: number[] = [];\n for (let i = 0; i < totalPages; i += 1) {\n if (i === resolvedPage) continue;\n if (!nextPages[i]) {\n pagesToFetch.push(i);\n }\n }\n for (const targetPage of pagesToFetch) {\n try {\n const res = await getSonarrSeries(\n category,\n targetPage,\n pageSize,\n query,\n { missingOnly: useMissing }\n );\n if (instanceKeyRef.current !== key) {\n break;\n }\n const pageIndex = res.page ?? targetPage;\n const pageSeries = res.series ?? [];\n const currentPages = instancePagesRef.current;\n const prevSnapshot = createFilteredSignature(currentPages[pageIndex] ?? [], useMissing);\n const nextSnapshot = createFilteredSignature(pageSeries, useMissing);\n if (prevSnapshot === nextSnapshot) {\n instancePagesRef.current = { ...currentPages, [pageIndex]: pageSeries };\n continue;\n }\n setInstancePages((prev) => {\n const updated = { ...prev, [pageIndex]: pageSeries };\n instancePagesRef.current = updated;\n return updated;\n });\n } catch {\n break;\n }\n }\n }\n } catch (error) {\n push(\n error instanceof Error\n ? error.message\n : `Failed to load ${category} series`,\n \"error\"\n );\n } finally {\n if (showLoading) {\n setInstanceLoading(false);\n }\n }\n },\n [push, onlyMissing]\n );\n\n const loadAggregate = useCallback(async () => {\n if (!instances.length) {\n setAggRows([]);\n setAggSummary({ available: 0, monitored: 0, missing: 0, total: 0 });\n return;\n }\n console.log(`[Sonarr Aggregate] Starting aggregation for ${instances.length} instances`);\n setAggLoading(true);\n try {\n const aggregated: SonarrAggRow[] = [];\n let totalAvailable = 0;\n let totalMonitored = 0;\n let totalMissing = 0;\n for (const inst of instances) {\n let page = 0;\n let counted = false;\n const label = inst.name || inst.category;\n console.log(`[Sonarr Aggregate] Processing instance: ${label}`);\n while (page < 200) {\n const res = await getSonarrSeries(\n inst.category,\n page,\n SONARR_AGG_FETCH_SIZE,\n \"\",\n { missingOnly: onlyMissing }\n );\n console.log(`[Sonarr Aggregate] Response for ${label} page ${page}:`, {\n total: res.total,\n page: res.page,\n page_size: res.page_size,\n series_count: res.series?.length ?? 0,\n counts: res.counts\n });\n if (!counted) {\n const counts = res.counts;\n if (counts) {\n totalAvailable += counts.available ?? 0;\n totalMonitored += counts.monitored ?? 0;\n totalMissing += counts.missing ?? 0;\n }\n counted = true;\n }\n const series = res.series ?? [];\n console.log(`[Sonarr Aggregate] Instance: ${label}, Page: ${page}, Series count: ${series.length}, Total episodes so far: ${aggregated.length}`);\n series.forEach((entry: SonarrSeriesEntry) => {\n const title =\n (entry.series?.[\"title\"] as string | undefined) || \"\";\n Object.entries(entry.seasons ?? {}).forEach(\n ([seasonNumber, season]) => {\n (season.episodes ?? []).forEach((episode: SonarrEpisode) => {\n aggregated.push({\n __instance: label,\n series: title,\n season: seasonNumber,\n episode: episode.episodeNumber ?? \"\",\n title: episode.title ?? \"\",\n monitored: !!episode.monitored,\n hasFile: !!episode.hasFile,\n airDate: episode.airDateUtc ?? \"\",\n });\n });\n }\n );\n });\n if (!series.length || series.length < SONARR_AGG_FETCH_SIZE) {\n console.log(`[Sonarr Aggregate] Breaking pagination for ${label} - series.length=${series.length}`);\n break;\n }\n page += 1;\n }\n }\n\n // Smart diffing: only update if data actually changed\n const uniqueSeries = new Set(aggregated.map(ep => `${ep.__instance}::${ep.series}`)).size;\n console.log(`[Sonarr Aggregate] Aggregation complete:`, {\n totalEpisodes: aggregated.length,\n uniqueSeries: uniqueSeries,\n instances: instances.length\n });\n setAggRows((prev) => {\n const prevJson = JSON.stringify(prev);\n const nextJson = JSON.stringify(aggregated);\n if (prevJson === nextJson) {\n console.log(`[Sonarr Aggregate] Data unchanged, skipping update`);\n return prev;\n }\n console.log(`[Sonarr Aggregate] Data changed, updating from ${prev.length} to ${aggregated.length} episodes`);\n return aggregated;\n });\n\n const newSummary = {\n available: totalAvailable,\n monitored: totalMonitored,\n missing: totalMissing,\n total: aggregated.length,\n };\n\n setAggSummary((prev) => {\n if (\n prev.available === newSummary.available &&\n prev.monitored === newSummary.monitored &&\n prev.missing === newSummary.missing &&\n prev.total === newSummary.total\n ) {\n return prev;\n }\n return newSummary;\n });\n\n // Only reset page if filter changed, not on refresh\n if (aggFilter !== globalSearch) {\n setAggPage(0);\n setAggFilter(globalSearch);\n }\n setAggUpdated(new Date().toLocaleTimeString());\n } catch (error) {\n setAggRows([]);\n setAggSummary({ available: 0, monitored: 0, missing: 0, total: 0 });\n push(\n error instanceof Error\n ? error.message\n : \"Failed to load aggregated Sonarr data\",\n \"error\"\n );\n } finally {\n setAggLoading(false);\n }\n }, [instances, globalSearch, push, onlyMissing]);\n\n useEffect(() => {\n if (!active) return;\n void loadInstances();\n }, [active, loadInstances]);\n\n useEffect(() => {\n if (!active) return;\n if (!selection || selection === \"aggregate\") return;\n setInstancePage(0);\n const query = globalSearchRef.current;\n void fetchInstance(selection, 0, query, {\n preloadAll: true,\n showLoading: true,\n missingOnly: onlyMissing,\n });\n }, [active, selection, fetchInstance]); // Removed onlyMissing to prevent refresh\n\n useEffect(() => {\n if (!active) return;\n if (selection !== \"aggregate\") return;\n void loadAggregate();\n }, [active, selection, loadAggregate]);\n\n useInterval(() => {\n if (selection === \"aggregate\" && liveArr) {\n void loadAggregate();\n }\n }, selection === \"aggregate\" && liveArr ? 10000 : null);\n\n useEffect(() => {\n if (!active) return;\n const handler = (term: string) => {\n if (selection === \"aggregate\") {\n setAggFilter(term);\n setAggPage(0);\n } else if (selection) {\n setInstancePage(0);\n void fetchInstance(selection, 0, term, {\n preloadAll: true,\n showLoading: true,\n missingOnly: onlyMissing,\n });\n }\n };\n register(handler);\n return () => clearHandler(handler);\n }, [active, selection, register, clearHandler, fetchInstance, onlyMissing]);\n\n useInterval(\n () => {\n if (selection && selection !== \"aggregate\") {\n const activeFilter = globalSearchRef.current?.trim?.() || \"\";\n if (activeFilter) {\n return;\n }\n void fetchInstance(selection, instancePage, instanceQuery, {\n preloadAll: false,\n showLoading: false,\n missingOnly: onlyMissing,\n });\n }\n },\n active && selection && selection !== \"aggregate\" && liveArr ? 1000 : null\n );\n\n useEffect(() => {\n globalSearchRef.current = globalSearch;\n }, [globalSearch]);\n\n useEffect(() => {\n if (selection === \"aggregate\") {\n setAggFilter(globalSearch);\n }\n }, [selection, globalSearch]);\n\n const filteredAggRows = useMemo(() => {\n let rows = aggRows;\n if (aggFilter) {\n const q = aggFilter.toLowerCase();\n rows = rows.filter((row) => {\n return (\n row.series.toLowerCase().includes(q) ||\n row.title.toLowerCase().includes(q) ||\n row.__instance.toLowerCase().includes(q)\n );\n });\n }\n if (reasonFilter !== \"all\") {\n if (reasonFilter === \"none\") {\n rows = rows.filter((row) => !row.reason);\n } else {\n rows = rows.filter((row) => row.reason === reasonFilter);\n }\n }\n return rows;\n }, [aggRows, aggFilter, reasonFilter]);\n\n const sortedAggRows = filteredAggRows;\n\n const aggPages = Math.max(\n 1,\n Math.ceil(sortedAggRows.length / SONARR_AGG_PAGE_SIZE)\n );\n const aggPageRows = sortedAggRows.slice(\n aggPage * SONARR_AGG_PAGE_SIZE,\n aggPage * SONARR_AGG_PAGE_SIZE + SONARR_AGG_PAGE_SIZE\n );\n\n const currentSeries = instancePages[instancePage] ?? [];\n\n const handleRestart = useCallback(async () => {\n if (!selection || selection === \"aggregate\") return;\n try {\n await restartArr(selection);\n push(`Restarted ${selection}`, \"success\");\n } catch (error) {\n push(\n error instanceof Error ? error.message : `Failed to restart ${selection}`,\n \"error\"\n );\n }\n }, [selection, push]);\n\n const handleInstanceSelection = useCallback(\n (event: ChangeEvent<HTMLSelectElement>) => {\n const next = (event.target.value || \"aggregate\") as string | \"aggregate\";\n setSelection(next);\n if (next !== \"aggregate\") {\n setGlobalSearch(\"\");\n }\n },\n [setSelection, setGlobalSearch]\n );\n\n const isAggregate = selection === \"aggregate\";\n\n return (\n <section className=\"card\">\n <div className=\"card-header\">Sonarr</div>\n <div className=\"card-body\">\n <div className=\"split\">\n <aside className=\"pane sidebar\">\n <button\n className={`btn ${isAggregate ? \"active\" : \"\"}`}\n onClick={() => setSelection(\"aggregate\")}\n >\n All Sonarr\n </button>\n {instances.map((inst) => (\n <button\n key={inst.category}\n className={`btn ghost ${\n selection === inst.category ? \"active\" : \"\"\n }`}\n onClick={() => {\n setSelection(inst.category);\n setGlobalSearch(\"\");\n }}\n >\n {inst.name || inst.category}\n </button>\n ))}\n </aside>\n <div className=\"pane\">\n <div className=\"field mobile-instance-select\">\n <label>Instance</label>\n <select\n value={selection || \"aggregate\"}\n onChange={handleInstanceSelection}\n disabled={!instances.length}\n >\n <option value=\"aggregate\">All Sonarr</option>\n {instances.map((inst) => (\n <option key={inst.category} value={inst.category}>\n {inst.name || inst.category}\n </option>\n ))}\n </select>\n </div>\n <div className=\"row\" style={{ alignItems: \"flex-end\", gap: \"12px\", flexWrap: \"wrap\" }}>\n <div className=\"col field\" style={{ flex: \"1 1 200px\" }}>\n <label>Search</label>\n <input\n placeholder=\"Filter series or episodes\"\n value={globalSearch}\n onChange={(event) => setGlobalSearch(event.target.value)}\n />\n </div>\n <div className=\"field\" style={{ flex: \"0 0 auto\", minWidth: \"140px\" }}>\n <label>Status</label>\n <select\n onChange={(event) => {\n const value = event.target.value;\n const newMissingState = value === \"missing\";\n setOnlyMissing(newMissingState);\n // Trigger refetch when filter changes for instance views\n if (selection && selection !== \"aggregate\") {\n void fetchInstance(selection, 0, globalSearchRef.current || \"\", {\n preloadAll: true,\n showLoading: true,\n missingOnly: newMissingState,\n });\n }\n }}\n value={onlyMissing ? \"missing\" : \"all\"}\n >\n <option value=\"all\">All Episodes</option>\n <option value=\"missing\">Missing Only</option>\n </select>\n </div>\n <div className=\"field\" style={{ flex: \"0 0 auto\", minWidth: \"140px\" }}>\n <label>Search Reason</label>\n <select\n onChange={(event) => setReasonFilter(event.target.value)}\n value={reasonFilter}\n >\n <option value=\"all\">All Reasons</option>\n <option value=\"none\">Not Being Searched</option>\n <option value=\"Missing\">Missing</option>\n <option value=\"Quality\">Quality</option>\n <option value=\"CustomFormat\">Custom Format</option>\n <option value=\"Upgrade\">Upgrade</option>\n <option value=\"Scheduled search\">Scheduled Search</option>\n </select>\n </div>\n </div>\n\n {isAggregate ? (\n <SonarrAggregateView\n loading={aggLoading}\n rows={sortedAggRows}\n total={sortedAggRows.length}\n page={aggPage}\n totalPages={aggPages}\n onPageChange={setAggPage}\n onRefresh={() => void loadAggregate()}\n lastUpdated={aggUpdated}\n groupSonarr={groupSonarr}\n summary={aggSummary}\n />\n ) : (\n <SonarrInstanceView\n loading={instanceLoading}\n counts={instanceData?.counts ?? null}\n series={currentSeries}\n page={instancePage}\n pageSize={instancePageSize}\n totalPages={instanceTotalPages}\n totalItems={instanceTotalItems}\n onlyMissing={onlyMissing}\n onPageChange={(page) => {\n setInstancePage(page);\n void fetchInstance(selection as string, page, instanceQuery, {\n preloadAll: false,\n showLoading: true,\n missingOnly: onlyMissing,\n });\n }}\n onRestart={() => void handleRestart()}\n lastUpdated={lastUpdated}\n groupSonarr={groupSonarr}\n />\n )}\n </div>\n </div>\n </div>\n </section>\n );\n}\n\ninterface SonarrAggregateViewProps {\n loading: boolean;\n rows: SonarrAggRow[];\n total: number;\n page: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n onRefresh: () => void;\n lastUpdated: string | null;\n groupSonarr: boolean;\n summary: { available: number; monitored: number; missing: number; total: number };\n}\n\nfunction SonarrAggregateView({\n loading,\n rows,\n total,\n page,\n totalPages,\n onPageChange,\n onRefresh,\n lastUpdated,\n groupSonarr,\n summary,\n}: SonarrAggregateViewProps): JSX.Element {\n // Create fully grouped data from all rows\n const allGroupedData = useMemo(() => {\n const instanceMap = new Map<string, Map<string, Map<string, SonarrAggRow[]>>>();\n\n rows.forEach(row => {\n const instance = row.__instance;\n const series = row.series;\n const season = String(row.season);\n\n if (!instanceMap.has(instance)) {\n instanceMap.set(instance, new Map());\n }\n const instanceSeriesMap = instanceMap.get(instance)!;\n\n if (!instanceSeriesMap.has(series)) {\n instanceSeriesMap.set(series, new Map());\n }\n const seasonMap = instanceSeriesMap.get(series)!;\n\n if (!seasonMap.has(season)) {\n seasonMap.set(season, []);\n }\n seasonMap.get(season)!.push(row);\n });\n\n const result: Array<{\n instance: string;\n series: string;\n subRows: Array<{\n seasonNumber: string;\n isSeason: boolean;\n subRows: Array<SonarrAggRow & { isEpisode: boolean }>;\n }>;\n }> = [];\n\n instanceMap.forEach((seriesMap, instance) => {\n seriesMap.forEach((seasonMap, series) => {\n result.push({\n instance,\n series,\n subRows: Array.from(seasonMap.entries()).map(([seasonNumber, episodes]) => ({\n seasonNumber,\n isSeason: true,\n subRows: episodes.map(ep => ({ ...ep, isEpisode: true }))\n }))\n });\n });\n });\n\n return result;\n }, [rows]);\n\n // For grouped view, paginate the series groups (not individual episodes)\n // For flat view, paginate the episode rows\n const groupedPageRows = useMemo(() => {\n const pageSize = 50;\n return allGroupedData.slice(page * pageSize, (page + 1) * pageSize);\n }, [allGroupedData, page]);\n\n const flatPageRows = useMemo(() => {\n const pageSize = 50;\n return rows.slice(page * pageSize, (page + 1) * pageSize);\n }, [rows, page]);\n\n const tableData = groupSonarr ? groupedPageRows : flatPageRows;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const groupedColumns = useMemo<ColumnDef<any>[]>(() => [\n {\n accessorKey: \"title\",\n header: \"Title\",\n cell: ({ row }) => {\n if (row.original.isEpisode) return row.original.title;\n if (row.original.isSeason) return `Season ${row.original.seasonNumber}`;\n return row.original.series;\n }\n },\n {\n accessorKey: \"monitored\",\n header: \"Monitored\",\n cell: ({ row }) => {\n const monitored = row.original.isEpisode ? row.original.monitored : row.original.monitored;\n return <span className=\"table-badge\">{monitored ? \"Yes\" : \"No\"}</span>;\n }\n },\n {\n accessorKey: \"hasFile\",\n header: \"Has File\",\n cell: ({ row }) => {\n if (row.original.isEpisode) {\n return <span className=\"table-badge\">{row.original.hasFile ? \"Yes\" : \"No\"}</span>;\n }\n return null;\n }\n },\n {\n accessorKey: \"airDate\",\n header: \"Air Date\",\n cell: ({ row }) => {\n if (row.original.isEpisode) {\n return row.original.airDate || \"—\";\n }\n return null;\n }\n },\n ], []);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const flatColumns = useMemo<ColumnDef<any>[]>(() => [\n {\n accessorKey: \"__instance\",\n header: \"Instance\",\n },\n {\n accessorKey: \"series\",\n header: \"Series\",\n },\n {\n accessorKey: \"season\",\n header: \"Season\",\n },\n {\n accessorKey: \"episode\",\n header: \"Episode\",\n },\n {\n accessorKey: \"title\",\n header: \"Title\",\n },\n {\n accessorKey: \"monitored\",\n header: \"Monitored\",\n cell: ({ getValue }) => (\n <span className=\"table-badge\">{getValue() ? \"Yes\" : \"No\"}</span>\n ),\n },\n {\n accessorKey: \"hasFile\",\n header: \"Has File\",\n cell: ({ getValue }) => (\n <span className=\"table-badge\">{getValue() ? \"Yes\" : \"No\"}</span>\n ),\n },\n {\n accessorKey: \"airDate\",\n header: \"Air Date\",\n cell: ({ getValue }) => getValue() || \"—\",\n },\n ], []);\n\n const columns = groupSonarr ? groupedColumns : flatColumns;\n\n // eslint-disable-next-line react-hooks/incompatible-library\n const groupedTable = useReactTable({\n data: tableData,\n columns,\n getCoreRowModel: getCoreRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n });\n\n const flatTable = useReactTable({\n data: tableData,\n columns,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n state: {\n pagination: {\n pageIndex: page,\n pageSize: 50,\n },\n },\n manualPagination: true,\n pageCount: totalPages,\n });\n\n const table = groupSonarr ? groupedTable : flatTable;\n\n const pageSize = 50;\n // For grouped view, paginate by series groups; for flat view, paginate by rows\n const effectiveTotalPages = groupSonarr\n ? Math.ceil(allGroupedData.length / pageSize)\n : Math.ceil(rows.length / pageSize);\n const safePage = Math.min(page, Math.max(0, effectiveTotalPages - 1));\n const totalItemsDisplay = groupSonarr\n ? `${allGroupedData.length} series`\n : rows.length.toLocaleString();\n\n return (\n <div className=\"stack animate-fade-in\">\n <div className=\"row\" style={{ justifyContent: \"space-between\" }}>\n <div className=\"hint\">\n Aggregated episodes across all instances{\" \"}\n {lastUpdated ? `(updated ${lastUpdated})` : \"\"}\n <br />\n <strong>Available:</strong>{\" \"}\n {summary.available.toLocaleString(undefined, { maximumFractionDigits: 0 })} •{\" \"}\n <strong>Monitored:</strong>{\" \"}\n {summary.monitored.toLocaleString(undefined, { maximumFractionDigits: 0 })} •{\" \"}\n <strong>Missing:</strong>{\" \"}\n {summary.missing.toLocaleString(undefined, { maximumFractionDigits: 0 })} •{\" \"}\n <strong>Total Episodes:</strong>{\" \"}\n {summary.total.toLocaleString(undefined, { maximumFractionDigits: 0 })}\n </div>\n <button className=\"btn ghost\" onClick={onRefresh} disabled={loading}>\n <IconImage src={RefreshIcon} />\n Refresh\n </button>\n </div>\n {loading ? (\n <div className=\"loading\">\n <span className=\"spinner\" /> Loading Sonarr library…\n </div>\n ) : groupSonarr ? (\n <div className=\"sonarr-hierarchical-view\">\n {groupedPageRows.map((seriesGroup: typeof groupedPageRows[number]) => (\n <details key={`${seriesGroup.instance}-${seriesGroup.series}`} className=\"series-details\">\n <summary className=\"series-summary\">\n <span className=\"series-title\">{seriesGroup.series}</span>\n <span className=\"series-instance\">({seriesGroup.instance})</span>\n </summary>\n <div className=\"series-content\">\n {seriesGroup.subRows.map((season: typeof seriesGroup.subRows[number]) => (\n <details key={`${seriesGroup.instance}-${seriesGroup.series}-${season.seasonNumber}`} className=\"season-details\">\n <summary className=\"season-summary\">\n <span className=\"season-title\">Season {season.seasonNumber}</span>\n <span className=\"season-count\">({season.subRows.length} episodes)</span>\n </summary>\n <div className=\"season-content\">\n <div className=\"episodes-table-wrapper\">\n <table className=\"episodes-table\">\n <thead>\n <tr>\n <th>Episode</th>\n <th>Title</th>\n <th>Monitored</th>\n <th>Has File</th>\n <th>Air Date</th>\n <th>Reason</th>\n </tr>\n </thead>\n <tbody>\n {season.subRows.map((episode) => (\n <tr key={`${episode.__instance}-${episode.series}-${episode.season}-${episode.episode}`}>\n <td>{episode.episode}</td>\n <td>{episode.title}</td>\n <td><span className=\"table-badge\">{episode.monitored ? \"Yes\" : \"No\"}</span></td>\n <td><span className=\"table-badge\">{episode.hasFile ? \"Yes\" : \"No\"}</span></td>\n <td>{episode.airDate || \"—\"}</td>\n <td>{episode.reason ? <span className=\"table-badge table-badge-reason\">{episode.reason}</span> : <span className=\"hint\">—</span>}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n </details>\n ))}\n </div>\n </details>\n ))}\n </div>\n ) : tableData.length ? (\n <div className=\"table-wrapper\">\n <table className=\"responsive-table\">\n <thead>\n <tr>\n {table.getFlatHeaders().map(header => (\n <th\n key={header.id}\n className={header.column.getCanSort() ? \"sortable\" : \"\"}\n onClick={header.column.getToggleSortingHandler()}\n >\n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n {header.column.getCanSort() && (\n <span className=\"sort-arrow\">\n {{\n asc: \"▲\",\n desc: \"▼\",\n }[header.column.getIsSorted() as string] ?? null}\n </span>\n )}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {table.getRowModel().rows.map(row => {\n const episode = row.original;\n const stableKey = `${episode.__instance}-${episode.series}-${episode.season}-${episode.episode}`;\n return (\n <tr key={stableKey}>\n {row.getVisibleCells().map(cell => (\n <td key={cell.id} data-label={cell.column.columnDef.header as string}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n ) : (\n <div className=\"hint\">No series found.</div>\n )}\n {tableData.length > 0 && (\n <div className=\"pagination\">\n <div>\n Page {safePage + 1} of {effectiveTotalPages} ({totalItemsDisplay} items ·\n page size {pageSize})\n </div>\n <div className=\"inline\">\n <button\n className=\"btn\"\n onClick={() => onPageChange(Math.max(0, safePage - 1))}\n disabled={safePage === 0 || loading}\n >\n Prev\n </button>\n <button\n className=\"btn\"\n onClick={() => onPageChange(Math.min(effectiveTotalPages - 1, safePage + 1))}\n disabled={safePage >= effectiveTotalPages - 1 || loading}\n >\n Next\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n\ninterface SonarrInstanceViewProps {\n loading: boolean;\n counts: { available: number; monitored: number; missing?: number } | null;\n series: SonarrSeriesEntry[];\n page: number;\n pageSize: number;\n totalPages: number;\n totalItems: number;\n onlyMissing: boolean;\n onPageChange: (page: number) => void;\n onRestart: () => void;\n lastUpdated: string | null;\n groupSonarr: boolean;\n}\n\nfunction SonarrInstanceView({\n loading,\n counts,\n series,\n page,\n pageSize,\n totalPages,\n\n onPageChange,\n groupSonarr,\n}: SonarrInstanceViewProps): JSX.Element {\n const safePage = Math.min(page, Math.max(0, totalPages - 1));\n\n // Transform series to SonarrAggRow[]\n const episodeRows = useMemo(() => {\n const rows: SonarrAggRow[] = [];\n for (const entry of series) {\n const title = (entry.series?.[\"title\"] as string | undefined) || \"\";\n Object.entries(entry.seasons ?? {}).forEach(([seasonNumber, season]) => {\n (season.episodes ?? []).forEach((episode) => {\n rows.push({\n __instance: \"Instance\",\n series: title,\n season: seasonNumber,\n episode: episode.episodeNumber ?? \"\",\n title: episode.title ?? \"\",\n monitored: !!episode.monitored,\n hasFile: !!episode.hasFile,\n airDate: episode.airDateUtc ?? \"\",\n });\n });\n });\n }\n return rows;\n }, [series]);\n\n // Group for hierarchical view\n const groupedTableData = useMemo(() => {\n const map = new Map<string, Map<string, SonarrAggRow[]>>();\n episodeRows.forEach(row => {\n const seriesKey = row.series;\n if (!map.has(seriesKey)) map.set(seriesKey, new Map());\n const seasons = map.get(seriesKey)!;\n const seasonKey = String(row.season);\n if (!seasons.has(seasonKey)) seasons.set(seasonKey, []);\n seasons.get(seasonKey)!.push(row);\n });\n return Array.from(map.entries()).map(([series, seasons]) => ({\n series,\n subRows: Array.from(seasons.entries()).map(([seasonNumber, episodes]) => ({\n seasonNumber,\n isSeason: true,\n subRows: episodes.map(ep => ({ ...ep, isEpisode: true }))\n }))\n }));\n }, [episodeRows]);\n\n return (\n <div className=\"stack animate-fade-in\">\n <div className=\"row\" style={{ justifyContent: \"space-between\" }}>\n <div className=\"hint\">\n {counts ? (\n <>\n <strong>Available:</strong> {counts.available.toLocaleString()} •{\" \"}\n <strong>Monitored:</strong> {counts.monitored.toLocaleString()} •{\" \"}\n <strong>Missing:</strong> {counts.missing?.toLocaleString() ?? 0}\n </>\n ) : (\n \"Loading series information...\"\n )}\n </div>\n </div>\n {loading ? (\n <div className=\"loading\">\n <span className=\"spinner\" /> Loading series…\n </div>\n ) : groupSonarr ? (\n <div className=\"sonarr-hierarchical-view\">\n {groupedTableData.map((series) => (\n <details key={`${series.series}`} className=\"series-details\">\n <summary className=\"series-summary\">\n <span className=\"series-title\">{series.series}</span>\n </summary>\n <div className=\"series-content\">\n {series.subRows.map((season) => (\n <details key={`${series.series}-${season.seasonNumber}`} className=\"season-details\">\n <summary className=\"season-summary\">\n <span className=\"season-title\">Season {season.seasonNumber}</span>\n <span className=\"season-count\">({season.subRows.length} episodes)</span>\n </summary>\n <div className=\"season-content\">\n <div className=\"episodes-table-wrapper\">\n <table className=\"episodes-table\">\n <thead>\n <tr>\n <th>Episode</th>\n <th>Title</th>\n <th>Monitored</th>\n <th>Has File</th>\n <th>Air Date</th>\n <th>Reason</th>\n </tr>\n </thead>\n <tbody>\n {season.subRows.map((episode: typeof season.subRows[number]) => (\n <tr key={`${episode.series}-${episode.season}-${episode.episode}`}>\n <td>{episode.episode}</td>\n <td>{episode.title}</td>\n <td><span className=\"table-badge\">{episode.monitored ? \"Yes\" : \"No\"}</span></td>\n <td><span className=\"table-badge\">{episode.hasFile ? \"Yes\" : \"No\"}</span></td>\n <td>{episode.airDate || \"—\"}</td>\n <td>{episode.reason ? <span className=\"table-badge table-badge-reason\">{episode.reason}</span> : <span className=\"hint\">—</span>}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n </details>\n ))}\n </div>\n </details>\n ))}\n </div>\n ) : episodeRows.length ? (\n <div className=\"table-wrapper\">\n <table className=\"responsive-table\">\n <thead>\n <tr>\n <th>Series</th>\n <th>Season</th>\n <th>Episode</th>\n <th>Title</th>\n <th>Monitored</th>\n <th>Has File</th>\n <th>Air Date</th>\n <th>Reason</th>\n </tr>\n </thead>\n <tbody>\n {episodeRows.slice(safePage * pageSize, safePage * pageSize + pageSize).map((row, idx) => (\n <tr key={`${row.series}-${row.season}-${row.episode}-${idx}`}>\n <td>{row.series}</td>\n <td>{row.season}</td>\n <td>{row.episode}</td>\n <td>{row.title}</td>\n <td><span className=\"table-badge\">{row.monitored ? \"Yes\" : \"No\"}</span></td>\n <td><span className=\"table-badge\">{row.hasFile ? \"Yes\" : \"No\"}</span></td>\n <td>{row.airDate || \"—\"}</td>\n <td>{row.reason ? <span className=\"table-badge table-badge-reason\">{row.reason}</span> : <span className=\"hint\">—</span>}</td>\n </tr>\n ))}\n </tbody>\n </table>\n <div className=\"pagination\">\n <div>\n Page {safePage + 1} of {totalPages} ({episodeRows.length.toLocaleString()} items · page size {pageSize})\n </div>\n <div className=\"inline\">\n <button\n className=\"btn\"\n onClick={() => onPageChange(Math.max(0, safePage - 1))}\n disabled={safePage === 0 || loading}\n >\n Prev\n </button>\n <button\n className=\"btn\"\n onClick={() => onPageChange(Math.min(totalPages - 1, safePage + 1))}\n disabled={safePage >= totalPages - 1 || loading}\n >\n Next\n </button>\n </div>\n </div>\n </div>\n ) : (\n <div className=\"hint\">No series found.</div>\n )}\n </div>\n );\n}\n","import { type JSX } from \"react\";\nimport { RadarrView } from \"./RadarrView\";\nimport { SonarrView } from \"./SonarrView\";\n\ninterface ArrViewProps {\n type: \"radarr\" | \"sonarr\";\n active: boolean;\n}\n\nexport function ArrView({ type, active }: ArrViewProps): JSX.Element {\n if (type === \"radarr\") {\n return <RadarrView active={active} />;\n }\n return <SonarrView active={active} />;\n}\n"],"names":["RADARR_PAGE_SIZE","RADARR_AGG_PAGE_SIZE","RADARR_AGG_FETCH_SIZE","RadarrAggregateView","loading","rows","total","page","totalPages","onPageChange","onRefresh","lastUpdated","sort","onSort","summary","columns","useMemo","info","jsx","reason","table","useReactTable","getCoreRowModel","jsxs","IconImage","RefreshIcon","headerGroup","header","sortKey","flexRender","row","movie","stableKey","cell","RadarrInstanceView","data","pageSize","allMovies","onlyMissing","reasonFilter","onRestart","filteredMovies","movies","m","reasonFilteredMovies","getSortedRowModel","RestartIcon","RadarrView","active","push","useToast","globalSearch","setGlobalSearch","register","clearHandler","useSearch","liveArr","setLiveArr","useWebUI","instances","setInstances","useState","selection","setSelection","instanceData","setInstanceData","instancePage","setInstancePage","instanceQuery","setInstanceQuery","instanceLoading","setInstanceLoading","setLastUpdated","instancePages","setInstancePages","instancePageSize","setInstancePageSize","instanceTotalPages","setInstanceTotalPages","instanceKeyRef","useRef","instancePagesRef","globalSearchRef","backendReadyWarnedRef","aggRows","setAggRows","aggLoading","setAggLoading","aggPage","setAggPage","aggFilter","setAggFilter","aggUpdated","setAggUpdated","aggSort","setAggSort","setOnlyMissing","setReasonFilter","aggSummary","setAggSummary","loadInstances","useCallback","getArrList","filtered","arr","error","preloadRemainingPages","category","query","pages","key","results","pg","res","getRadarrMovies","resolved","prev","next","hasChanges","existingMovies","fetchInstance","options","preloadAll","keyChanged","response","resolvedPage","totalItems","existingPages","moviesChanged","pagesToFetch","i","loadAggregate","aggregated","totalAvailable","totalMonitored","inst","counted","label","counts","prevJson","nextJson","newSummary","useEffect","useInterval","handler","term","filteredAggRows","q","title","instance","sortedAggRows","list","getValue","a","b","valueA","valueB","comparison","aggPages","aggPageRows","allInstanceMovies","handleRestart","restartArr","handleInstanceSelection","event","isAggregate","value","SONARR_PAGE_SIZE","SONARR_AGG_PAGE_SIZE","SONARR_AGG_FETCH_SIZE","filterSeriesEntriesForMissing","seriesEntries","result","entry","seasons","filteredSeasons","seasonNumber","season","episodes","episode","createFilteredSignature","SonarrView","groupSonarr","setGroupSonarr","instanceDataRef","instanceTotalItems","setInstanceTotalItems","showLoading","missingOnly","useMissing","getSonarrSeries","series","prevPages","nextPages","prevSignature","nextSignature","shouldUpdateCurrentPage","prevCounts","nextCounts","targetPage","pageIndex","pageSeries","currentPages","prevSnapshot","nextSnapshot","updated","totalMissing","uniqueSeries","ep","currentSeries","newMissingState","SonarrAggregateView","SonarrInstanceView","allGroupedData","instanceMap","instanceSeriesMap","seasonMap","seriesMap","groupedPageRows","flatPageRows","tableData","groupedColumns","monitored","flatColumns","groupedTable","getExpandedRowModel","flatTable","getPaginationRowModel","effectiveTotalPages","safePage","totalItemsDisplay","seriesGroup","episodeRows","groupedTableData","map","seriesKey","seasonKey","Fragment","idx","ArrView","type"],"mappings":"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"}
|