pinokiod 8.0.16 → 8.0.18

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.
@@ -185,7 +185,9 @@ report_errors: false`)
185
185
  install_path_exists = await this.kernel.exists(`bin/${CONDA_ROOT_DIR}`)
186
186
  if (install_path_exists) {
187
187
  console.log("Removing existing install path...", install_path)
188
+ ondata({ raw: `removing existing Miniforge installation...\r\n` })
188
189
  await this.removeInstallPath(install_path, ondata)
190
+ ondata({ raw: `existing Miniforge installation removed.\r\n` })
189
191
  }
190
192
 
191
193
  // 2. run the script
@@ -252,27 +254,7 @@ report_errors: false`)
252
254
  }
253
255
  async removeInstallPath(target, ondata) {
254
256
  try {
255
- const stat = await fs.promises.lstat(target).catch((error) => {
256
- if (error && error.code === "ENOENT") {
257
- return null
258
- }
259
- throw error
260
- })
261
- if (!stat) {
262
- return
263
- }
264
- if (stat.isSymbolicLink()) {
265
- await removePath(target, {
266
- force: true,
267
- operation: "Updating Miniforge",
268
- })
269
- return
270
- }
271
- await removePath(target, {
272
- recursive: true,
273
- force: true,
274
- operation: "Updating Miniforge",
275
- })
257
+ await removePath(target)
276
258
  } catch (error) {
277
259
  if (isPathRemovalBlockedError(error)) {
278
260
  if (typeof ondata === "function") {
@@ -3,7 +3,6 @@ const path = require("path")
3
3
  const { inspectWindowsFileLocks } = require("./windows_restart_manager")
4
4
 
5
5
  const PATH_REMOVAL_BLOCKED_CODE = "PINOKIO_PATH_REMOVE_BLOCKED"
6
- const PATH_REMOVAL_PENDING_CODE = "PINOKIO_PATH_REMOVE_PENDING"
7
6
  const REMAINING_PREVIEW_LIMIT = 20
8
7
 
9
8
  class PathRemovalBlockedError extends Error {
@@ -16,21 +15,17 @@ class PathRemovalBlockedError extends Error {
16
15
  this.name = "PathRemovalBlockedError"
17
16
  this.code = PATH_REMOVAL_BLOCKED_CODE
18
17
  this.target = details.target
19
- this.operation = details.operation || "Removing files"
20
18
  this.causeCode = cause && cause.code ? cause.code : ""
21
19
  const remaining = Array.isArray(details.remaining) ? details.remaining : []
22
20
  this.remaining = remaining.slice(0, REMAINING_PREVIEW_LIMIT)
23
21
  this.remainingCount = remaining.length
24
22
  this.blockers = blockers
25
- this.cause = cause
26
23
  }
27
24
 
28
25
  toJSON() {
29
26
  return {
30
27
  code: this.code,
31
- message: this.message,
32
28
  target: this.target,
33
- operation: this.operation,
34
29
  causeCode: this.causeCode,
35
30
  remaining: this.remaining,
36
31
  remainingCount: this.remainingCount,
@@ -39,21 +34,25 @@ class PathRemovalBlockedError extends Error {
39
34
  }
40
35
  }
41
36
 
42
- class PathRemovalPendingError extends Error {
43
- constructor(target, cause) {
44
- super(`Windows still could not remove ${target}.`)
45
- this.name = "PathRemovalPendingError"
46
- this.code = PATH_REMOVAL_PENDING_CODE
47
- this.cause = cause
48
- }
37
+ const isPathRemovalBlockedError = (error) => !!(error && error.code === PATH_REMOVAL_BLOCKED_CODE)
38
+
39
+ const isInside = (target, candidate) => {
40
+ const relative = path.relative(target, candidate)
41
+ return relative === "" || (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative))
49
42
  }
50
43
 
51
- const isPathRemovalBlockedError = (error) => !!(error && error.code === PATH_REMOVAL_BLOCKED_CODE)
52
- const isPathRemovalPendingError = (error) => !!(error && error.code === PATH_REMOVAL_PENDING_CODE)
44
+ const pathExists = async (target, fsPromises) => {
45
+ try {
46
+ await fsPromises.lstat(target)
47
+ return true
48
+ } catch (error) {
49
+ return !error || error.code !== "ENOENT"
50
+ }
51
+ }
53
52
 
54
53
  const collectRemaining = async (target, fsPromises = fs.promises) => {
55
- const files = []
56
- const paths = []
54
+ const remaining = []
55
+ const regularFiles = []
57
56
  const pending = [path.resolve(target)]
58
57
 
59
58
  while (pending.length > 0) {
@@ -65,28 +64,40 @@ const collectRemaining = async (target, fsPromises = fs.promises) => {
65
64
  if (error && error.code === "ENOENT") {
66
65
  continue
67
66
  }
68
- paths.push(current)
67
+ remaining.push(current)
69
68
  continue
70
69
  }
71
70
 
72
- paths.push(current)
73
- if (!stat.isDirectory() || stat.isSymbolicLink()) {
74
- files.push(current)
71
+ if (!stat.isDirectory()) {
72
+ remaining.push(current)
73
+ if (stat.isFile()) {
74
+ regularFiles.push(current)
75
+ }
75
76
  continue
76
77
  }
77
78
 
78
79
  let entries
79
80
  try {
80
- entries = await fsPromises.readdir(current, { withFileTypes: true })
81
- } catch (_) {
81
+ entries = await fsPromises.readdir(current)
82
+ } catch (error) {
83
+ if (error.code !== "ENOENT") {
84
+ remaining.push(current)
85
+ }
86
+ continue
87
+ }
88
+ if (entries.length === 0) {
89
+ remaining.push(current)
82
90
  continue
83
91
  }
84
92
  for (const entry of entries) {
85
- pending.push(path.resolve(current, entry.name))
93
+ const child = path.resolve(current, entry)
94
+ if (isInside(target, child)) {
95
+ pending.push(child)
96
+ }
86
97
  }
87
98
  }
88
99
 
89
- return { files, paths }
100
+ return { remaining, regularFiles }
90
101
  }
91
102
 
92
103
  const createPathRemover = (dependencies = {}) => {
@@ -94,44 +105,36 @@ const createPathRemover = (dependencies = {}) => {
94
105
  const platform = dependencies.platform || process.platform
95
106
  const inspectLocks = dependencies.inspectLocks || inspectWindowsFileLocks
96
107
 
97
- return async (target, options = {}) => {
108
+ return async (target) => {
98
109
  const resolvedTarget = path.resolve(target)
99
- const {
100
- operation = "Removing files",
101
- diagnose = true,
102
- ...rmOptions
103
- } = options
104
110
 
105
111
  try {
106
- await fsPromises.rm(resolvedTarget, rmOptions)
107
- return { removed: true, target: resolvedTarget }
112
+ await fsPromises.rm(resolvedTarget, { recursive: true, force: true })
108
113
  } catch (error) {
109
114
  if (platform !== "win32") {
110
115
  throw error
111
116
  }
112
- if (!diagnose) {
113
- throw new PathRemovalPendingError(resolvedTarget, error)
114
- }
115
117
 
116
- const remaining = await collectRemaining(resolvedTarget, fsPromises)
117
- if (remaining.paths.length === 0) {
118
- throw error
118
+ if (!(await pathExists(resolvedTarget, fsPromises))) {
119
+ return
120
+ }
121
+ const diagnosis = await collectRemaining(resolvedTarget, fsPromises)
122
+ if (!(await pathExists(resolvedTarget, fsPromises))) {
123
+ return
119
124
  }
120
125
 
121
- let inspection = { blockers: [] }
122
- try {
123
- inspection = await inspectLocks(remaining.files)
124
- } catch (inspectionError) {
125
- console.warn("[path removal] Restart Manager inspection failed", inspectionError)
126
+ let blockers = []
127
+ if (diagnosis.regularFiles.length > 0) {
128
+ blockers = await inspectLocks(diagnosis.regularFiles).catch(() => [])
129
+ if (!Array.isArray(blockers)) blockers = []
126
130
  }
127
131
 
128
- const remainingItems = remaining.files.length > 0 ? remaining.files : remaining.paths
132
+ const remaining = diagnosis.remaining.length > 0 ? diagnosis.remaining : [resolvedTarget]
129
133
 
130
134
  throw new PathRemovalBlockedError({
131
135
  target: resolvedTarget,
132
- operation,
133
- remaining: remainingItems,
134
- blockers: inspection.blockers,
136
+ remaining,
137
+ blockers,
135
138
  }, error)
136
139
  }
137
140
  }
@@ -141,10 +144,8 @@ const removePath = createPathRemover()
141
144
 
142
145
  module.exports = {
143
146
  PATH_REMOVAL_BLOCKED_CODE,
144
- PATH_REMOVAL_PENDING_CODE,
145
- collectRemaining,
147
+ PathRemovalBlockedError,
146
148
  createPathRemover,
147
149
  isPathRemovalBlockedError,
148
- isPathRemovalPendingError,
149
150
  removePath,
150
151
  }
@@ -1,5 +1,3 @@
1
- const path = require("path")
2
-
3
1
  const ERROR_SUCCESS = 0
4
2
  const ERROR_MORE_DATA = 234
5
3
  const CCH_RM_SESSION_KEY = 32
@@ -16,7 +14,6 @@ const initialize = () => {
16
14
 
17
15
  const koffi = require("koffi")
18
16
  const library = koffi.load("rstrtmgr.dll")
19
- const kernel32 = koffi.load("kernel32.dll")
20
17
  const fileTime = koffi.struct({
21
18
  dwLowDateTime: "uint32_t",
22
19
  dwHighDateTime: "uint32_t",
@@ -42,34 +39,10 @@ const initialize = () => {
42
39
  registerResources: library.func("uint32_t __stdcall RmRegisterResources(uint32_t session, uint32_t fileCount, const str16 *files, uint32_t applicationCount, const void *applications, uint32_t serviceCount, const str16 *services)"),
43
40
  getList: library.func("uint32_t __stdcall RmGetList(uint32_t session, _Out_ uint32_t *needed, _Inout_ uint32_t *count, _Out_ void *processes, _Out_ uint32_t *rebootReasons)"),
44
41
  endSession: library.func("uint32_t __stdcall RmEndSession(uint32_t session)"),
45
- openProcess: kernel32.func("void * __stdcall OpenProcess(uint32_t access, int32_t inheritHandle, uint32_t processId)"),
46
- queryFullProcessImageName: kernel32.func("int32_t __stdcall QueryFullProcessImageNameW(void *process, uint32_t flags, _Out_ void *filename, _Inout_ uint32_t *size)"),
47
- closeHandle: kernel32.func("int32_t __stdcall CloseHandle(void *handle)"),
48
42
  }
49
43
  return bindings
50
44
  }
51
45
 
52
- const queryProcessImage = (api, pid) => {
53
- const PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
54
- const handle = api.openProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid)
55
- if (!handle) {
56
- return ""
57
- }
58
- try {
59
- const capacity = 32768
60
- const buffer = Buffer.alloc(capacity * 2)
61
- const size = [capacity]
62
- if (!api.queryFullProcessImageName(handle, 0, buffer, size)) {
63
- return ""
64
- }
65
- return String(api.koffi.decode.string16(buffer) || "")
66
- } catch (_) {
67
- return ""
68
- } finally {
69
- api.closeHandle(handle)
70
- }
71
- }
72
-
73
46
  const normalizeProcessInfo = (entry) => {
74
47
  const uniqueProcess = entry && entry.Process ? entry.Process : {}
75
48
  const pid = Number(uniqueProcess.dwProcessId) || 0
@@ -82,13 +55,13 @@ const normalizeProcessInfo = (entry) => {
82
55
 
83
56
  const inspectWindowsFileLocks = async (files) => {
84
57
  if (process.platform !== "win32") {
85
- return { blockers: [] }
58
+ return []
86
59
  }
87
60
 
88
61
  const resources = Array.from(new Set((Array.isArray(files) ? files : [])
89
62
  .filter((file) => typeof file === "string" && file.length > 0)))
90
63
  if (resources.length === 0) {
91
- return { blockers: [] }
64
+ return []
92
65
  }
93
66
 
94
67
  const api = initialize()
@@ -110,7 +83,7 @@ const inspectWindowsFileLocks = async (files) => {
110
83
  let rebootReasons = [0]
111
84
  status = api.getList(session[0], needed, count, null, rebootReasons)
112
85
  if (status === ERROR_SUCCESS && needed[0] === 0) {
113
- return { blockers: [] }
86
+ return []
114
87
  }
115
88
  if (status !== ERROR_MORE_DATA && status !== ERROR_SUCCESS) {
116
89
  throw new Error(`RmGetList failed with Windows error ${status}`)
@@ -128,14 +101,7 @@ const inspectWindowsFileLocks = async (files) => {
128
101
  const blockers = entries
129
102
  .map(normalizeProcessInfo)
130
103
  .filter((entry) => entry.pid > 0)
131
- .map((entry) => {
132
- const imagePath = queryProcessImage(api, entry.pid)
133
- return {
134
- ...entry,
135
- executable: imagePath ? path.win32.basename(imagePath) : "",
136
- }
137
- })
138
- return { blockers }
104
+ return blockers
139
105
  }
140
106
  if (status !== ERROR_MORE_DATA) {
141
107
  throw new Error(`RmGetList failed with Windows error ${status}`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "8.0.16",
3
+ "version": "8.0.18",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -34,7 +34,7 @@ const Git = require("../kernel/git")
34
34
  const TerminalApi = require('../kernel/api/terminal')
35
35
  const PluginSources = require("../kernel/plugin_sources")
36
36
  const ManagedSkills = require("../kernel/managed_skills")
37
- const { isPathRemovalBlockedError, isPathRemovalPendingError, removePath } = require("../kernel/path_removal")
37
+ const { isPathRemovalBlockedError, removePath } = require("../kernel/path_removal")
38
38
 
39
39
  const git = require('isomorphic-git')
40
40
  const http = require('isomorphic-git/http/node')
@@ -63,40 +63,6 @@ const ex = fn => (req, res, next) => {
63
63
  Promise.resolve(fn(req, res, next)).catch(next);
64
64
  };
65
65
 
66
- const isPathInsideRoot = (candidatePath, rootPath) => {
67
- const relative = path.relative(rootPath, candidatePath)
68
- return relative === "" || (
69
- relative !== ".."
70
- && !relative.startsWith(`..${path.sep}`)
71
- && !path.isAbsolute(relative)
72
- )
73
- }
74
-
75
- const resolveAppRemovalPath = async (apiRoot, name) => {
76
- if (typeof name !== "string" || !name || name.includes("\0")) {
77
- return null
78
- }
79
- const root = path.resolve(apiRoot)
80
- const target = path.resolve(root, name)
81
- if (target === root || !isPathInsideRoot(target, root)) {
82
- return null
83
- }
84
- const stat = await fs.promises.lstat(target).catch((error) => {
85
- if (error && error.code === "ENOENT") return null
86
- throw error
87
- })
88
- if (stat && !stat.isSymbolicLink()) {
89
- const [realRoot, realTarget] = await Promise.all([
90
- fs.promises.realpath(root),
91
- fs.promises.realpath(target),
92
- ])
93
- if (realTarget === realRoot || !isPathInsideRoot(realTarget, realRoot)) {
94
- return null
95
- }
96
- }
97
- return target
98
- }
99
-
100
66
 
101
67
 
102
68
 
@@ -16297,41 +16263,24 @@ class Server {
16297
16263
  console.timeEnd("/p/" + req.params.name + "/" + d)
16298
16264
  }))
16299
16265
  this.app.post("/pinokio/delete", ex(async (req, res) => {
16300
- if (!privacyFilterCache.isInstallRequestAllowed(req)) {
16301
- res.status(403).json({ error: "Cross-site deletion is not allowed" })
16302
- return
16303
- }
16304
16266
  try {
16305
16267
  if (req.body.type === 'conda-runtime') {
16306
16268
  for (const runtimeName of ["miniconda", "miniforge"]) {
16307
16269
  const runtimePath = this.kernel.path("bin", runtimeName)
16308
- await removePath(runtimePath, {
16309
- recursive: true,
16310
- force: true,
16311
- diagnose: req.body.background !== true,
16312
- operation: "Updating Miniforge",
16313
- })
16270
+ await removePath(runtimePath)
16314
16271
  }
16315
16272
  res.json({ success: true })
16316
16273
  } else if (req.body.type === 'bin') {
16317
16274
  let folderPath = this.kernel.path("bin")
16318
- await removePath(folderPath, {
16319
- recursive: true,
16320
- force: true,
16321
- diagnose: req.body.background !== true,
16322
- operation: "Resetting managed tools",
16323
- })
16275
+ const removalStartedAt = Date.now()
16276
+ console.log(`[fresh install] removing bin: start ${folderPath}`)
16277
+ await removePath(folderPath)
16278
+ console.log(`[fresh install] removing bin: complete (${((Date.now() - removalStartedAt) / 1000).toFixed(1)}s)`)
16324
16279
  await fs.promises.mkdir(folderPath, { recursive: true }).catch((e) => { })
16325
- await this.kernel.bin.refreshInstalled()
16326
16280
  res.json({ success: true })
16327
16281
  } else if (req.body.type === 'cache') {
16328
16282
  let folderPath = this.kernel.path("cache")
16329
- await removePath(folderPath, {
16330
- recursive: true,
16331
- force: true,
16332
- diagnose: req.body.background !== true,
16333
- operation: "Clearing the Pinokio cache",
16334
- })
16283
+ await removePath(folderPath)
16335
16284
  await fs.promises.mkdir(folderPath, { recursive: true }).catch((e) => { })
16336
16285
  await Environment.ensurePinokioCacheDirs(this.kernel, {
16337
16286
  throwOnFailure: true
@@ -16348,17 +16297,8 @@ class Server {
16348
16297
  }
16349
16298
  res.json({ success: true })
16350
16299
  } else if (req.body.name) {
16351
- const folderPath = await resolveAppRemovalPath(this.kernel.path("api"), req.body.name)
16352
- if (!folderPath) {
16353
- res.status(400).json({ error: "Invalid app deletion path" })
16354
- return
16355
- }
16356
- await removePath(folderPath, {
16357
- recursive: true,
16358
- force: true,
16359
- diagnose: req.body.background !== true,
16360
- operation: `Deleting ${req.body.name}`,
16361
- })
16300
+ let folderPath = this.kernel.path("api", req.body.name)
16301
+ await removePath(folderPath)
16362
16302
  // await fs.promises.mkdir(folderPath, { recursive: true }).catch((e) => { })
16363
16303
  await new Promise((resolve, reject) => {
16364
16304
  setTimeout(() => {
@@ -16369,10 +16309,6 @@ class Server {
16369
16309
  res.json({ success: true })
16370
16310
  }
16371
16311
  } catch(err) {
16372
- if (isPathRemovalPendingError(err)) {
16373
- res.status(423).json({ success: false, pending: true })
16374
- return
16375
- }
16376
16312
  if (isPathRemovalBlockedError(err)) {
16377
16313
  res.status(423).json({ success: false, error: err.toJSON() })
16378
16314
  return
@@ -27,7 +27,6 @@ const PinokioPathRemoval = (() => {
27
27
  const renderBlocker = (blocker) => {
28
28
  const name = blocker.name || blocker.serviceName || `Process ${blocker.pid || ""}`
29
29
  const detail = [
30
- blocker.executable && blocker.executable !== name ? blocker.executable : "",
31
30
  blocker.serviceName && blocker.serviceName !== name ? blocker.serviceName : "",
32
31
  blocker.pid ? `PID ${blocker.pid}` : "",
33
32
  ].filter(Boolean).join(" · ")
@@ -44,7 +43,7 @@ const PinokioPathRemoval = (() => {
44
43
  const itemLabel = itemCount === 1 ? "one remaining item" : `${itemCount || "some"} remaining items`
45
44
  const causeCode = details.causeCode ? ` (${escapeHtml(details.causeCode)})` : ""
46
45
  const explanation = blockers.length > 0
47
- ? `Windows couldn't remove ${itemLabel} because ${itemCount === 1 ? "it is" : "they are"} still in use.`
46
+ ? `Windows couldn't remove ${itemLabel} because one or more files are still in use.`
48
47
  : `Windows couldn't remove ${itemLabel}${causeCode}. No application was identified. Check permissions or security software.`
49
48
  const blockerHtml = blockers.length > 0
50
49
  ? `<ul class="pinokio-path-blocker-list">${blockers.map(renderBlocker).join("")}</ul>`
@@ -69,27 +68,15 @@ const PinokioPathRemoval = (() => {
69
68
  }
70
69
 
71
70
  const parseResponse = async (response) => {
72
- if (!response || typeof response.json !== "function") {
73
- return response
74
- }
75
- const fallbackResponse = typeof response.clone === "function" ? response.clone() : null
76
- let payload
77
- try {
78
- payload = await response.json()
79
- } catch (_) {
80
- const text = fallbackResponse && typeof fallbackResponse.text === "function"
81
- ? await fallbackResponse.text()
82
- : ""
83
- throw new Error(text || `Request failed (${response.status || "unknown"})`)
84
- }
85
- if (!response.ok && !blockedDetails(payload) && !(payload && payload.pending === true)) {
71
+ const payload = await response.json()
72
+ if (!response.ok && !blockedDetails(payload)) {
86
73
  const message = payload && payload.error
87
74
  throw new Error(typeof message === "string" ? message : `Request failed (${response.status})`)
88
75
  }
89
76
  return payload
90
77
  }
91
78
 
92
- const show = async ({ details, retry }) => {
79
+ const show = ({ details, retry }) => {
93
80
  if (typeof Swal === "undefined" || !Swal || typeof Swal.fire !== "function") {
94
81
  return { cancelled: true }
95
82
  }
@@ -99,7 +86,7 @@ const PinokioPathRemoval = (() => {
99
86
  let settled = false
100
87
  let timer = null
101
88
 
102
- return await new Promise((resolve) => {
89
+ return new Promise((resolve) => {
103
90
  const finish = (result) => {
104
91
  if (settled) return
105
92
  settled = true
@@ -123,18 +110,20 @@ const PinokioPathRemoval = (() => {
123
110
  retrying = true
124
111
  if (manual && typeof Swal.disableButtons === "function") Swal.disableButtons()
125
112
  try {
126
- const result = await retry(manual)
113
+ const result = await retry()
127
114
  if (settled) return false
128
- if (result && result.pending === true) {
129
- return false
130
- }
131
115
  const nextBlocked = blockedDetails(result)
132
116
  if (nextBlocked) {
133
- current = nextBlocked
134
- update()
135
- if (manual) Swal.showValidationMessage("Windows still cannot remove the remaining items.")
117
+ if (manual) {
118
+ current = nextBlocked
119
+ update()
120
+ Swal.showValidationMessage("Windows still cannot remove the remaining items.")
121
+ }
136
122
  return false
137
123
  }
124
+ if (result && result.error) {
125
+ throw new Error(typeof result.error === "string" ? result.error : "Retry failed.")
126
+ }
138
127
  finish(result)
139
128
  return true
140
129
  } catch (error) {
@@ -147,7 +136,7 @@ const PinokioPathRemoval = (() => {
147
136
  }
148
137
 
149
138
  Swal.fire({
150
- title: escapeHtml(current.operation || "File removal paused"),
139
+ title: "File removal paused",
151
140
  html: render(current),
152
141
  showCancelButton: true,
153
142
  confirmButtonText: "Try again now",
@@ -157,13 +146,7 @@ const PinokioPathRemoval = (() => {
157
146
  didOpen: () => {
158
147
  timer = setInterval(() => attempt(false), RETRY_INTERVAL)
159
148
  },
160
- preConfirm: async () => {
161
- const done = await attempt(true)
162
- return done ? true : false
163
- },
164
- willClose: () => {
165
- if (timer) clearInterval(timer)
166
- },
149
+ preConfirm: () => attempt(true),
167
150
  }).then((result) => {
168
151
  if (!settled && !result.isConfirmed) {
169
152
  finish({ cancelled: true })
@@ -172,9 +155,14 @@ const PinokioPathRemoval = (() => {
172
155
  })
173
156
  }
174
157
 
175
- const request = async (requestFactory) => {
176
- const execute = async (background = false) => parseResponse(await requestFactory(background))
177
- const initial = await execute()
158
+ const tryRemove = async (payload) => parseResponse(await fetch("/pinokio/delete", {
159
+ method: "post",
160
+ headers: { "Content-Type": "application/json" },
161
+ body: JSON.stringify(payload),
162
+ }))
163
+
164
+ const remove = async (payload) => {
165
+ const initial = await tryRemove(payload)
178
166
  const details = blockedDetails(initial)
179
167
  if (!details) {
180
168
  return initial
@@ -184,14 +172,14 @@ const PinokioPathRemoval = (() => {
184
172
  }
185
173
  return show({
186
174
  details,
187
- retry: (manual) => execute(!manual),
175
+ retry: () => tryRemove(payload),
188
176
  })
189
177
  }
190
178
 
191
179
  return {
192
- blockedDetails,
193
- request,
180
+ remove,
194
181
  show,
182
+ tryRemove,
195
183
  }
196
184
  })()
197
185
 
@@ -6985,10 +6985,6 @@ body.dark .swal2-popup.swal2-modal:not(.loader-popup):not(.pinokio-download-moda
6985
6985
  }
6986
6986
 
6987
6987
  .pinokio-path-blocker-item {
6988
- display: flex;
6989
- align-items: baseline;
6990
- justify-content: space-between;
6991
- gap: 16px;
6992
6988
  padding: 8px 0;
6993
6989
  border-bottom: 1px solid rgba(127, 127, 127, 0.18);
6994
6990
  }
@@ -6998,26 +6994,18 @@ body.dark .swal2-popup.swal2-modal:not(.loader-popup):not(.pinokio-download-moda
6998
6994
  }
6999
6995
 
7000
6996
  .pinokio-path-blocker-detail {
6997
+ display: block;
7001
6998
  font-size: 12px;
7002
6999
  overflow-wrap: anywhere;
7003
- text-align: right;
7004
7000
  }
7005
7001
 
7006
7002
  .pinokio-path-blocker-files {
7007
7003
  margin: 0 0 14px;
7008
7004
  }
7009
7005
 
7010
- .pinokio-path-blocker-files summary {
7011
- cursor: pointer;
7012
- }
7013
-
7014
- .pinokio-path-blocker-files div {
7015
- display: grid;
7016
- gap: 6px;
7017
- margin-top: 8px;
7018
- }
7019
-
7020
7006
  .pinokio-path-blocker-files code {
7007
+ display: block;
7008
+ margin-top: 6px;
7021
7009
  overflow-wrap: anywhere;
7022
7010
  white-space: normal;
7023
7011
  }
@@ -7027,14 +7015,3 @@ body.dark .swal2-popup.swal2-modal:not(.loader-popup):not(.pinokio-download-moda
7027
7015
  align-items: center;
7028
7016
  gap: 8px;
7029
7017
  }
7030
-
7031
- @media (max-width: 560px) {
7032
- .pinokio-path-blocker-item {
7033
- display: grid;
7034
- gap: 2px;
7035
- }
7036
-
7037
- .pinokio-path-blocker-detail {
7038
- text-align: left;
7039
- }
7040
- }
@@ -11866,13 +11866,7 @@ const rerenderMenuSection = (container, html) => {
11866
11866
  actions: "hidden"
11867
11867
  }
11868
11868
  });
11869
- let res = await PinokioPathRemoval.request((background) => fetch("/pinokio/delete", {
11870
- method: "post",
11871
- headers: {
11872
- "Content-Type": "application/json"
11873
- },
11874
- body: JSON.stringify({ name, background })
11875
- }))
11869
+ let res = await PinokioPathRemoval.remove({ name })
11876
11870
  console.log("res", res)
11877
11871
  Swal.close()
11878
11872
  if (res) {
@@ -231,13 +231,7 @@ document.addEventListener("DOMContentLoaded", async () => {
231
231
  if (proceed) {
232
232
  document.querySelector(".reset-bin-loading").classList.remove("hidden")
233
233
  document.querySelector("#del-bin").classList.add("hidden")
234
- let res = await PinokioPathRemoval.request((background) => fetch("/pinokio/delete", {
235
- method: "post",
236
- headers: {
237
- "Content-Type": "application/json"
238
- },
239
- body: JSON.stringify({ type: "bin", background })
240
- }))
234
+ let res = await PinokioPathRemoval.remove({ type: "bin" })
241
235
  console.log(res)
242
236
  document.querySelector(".reset-bin-loading").classList.add("hidden")
243
237
  if (res.cancelled) {