@gentbajko/slopify 3.8.4 → 3.8.6
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.
- package/dist/edge/http/studio.js +3 -1
- package/dist/extension/slopify-studio-chrome.zip +0 -0
- package/dist/extension/slopify-studio-firefox.zip +0 -0
- package/dist/patch-notes/3.8.5.md +9 -0
- package/dist/patch-notes/3.8.6.md +12 -0
- package/dist/patch-notes/index.json +12 -0
- package/dist/slices/studio/model.js +2 -0
- package/dist/slices/studio/pack.js +10 -4
- package/dist/slices/studio/settings.js +9 -2
- package/dist/web/assets/{index-DzehNHWU.js → index-CAkfWk98.js} +2 -2
- package/dist/web/assets/{index-BLtujGrO.css → index-D4rGFI9z.css} +1 -1
- package/dist/web/assets/{pdf-BPNXDDg1.js → pdf-DlfMpxou.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
package/dist/edge/http/studio.js
CHANGED
|
@@ -14,7 +14,7 @@ import { readSetting, writeSetting } from "../../slices/settings/repo.js";
|
|
|
14
14
|
import { findDownload } from "../../slices/storage/downloads.js";
|
|
15
15
|
import { backfillVideos } from "../../slices/studio/backfill.js";
|
|
16
16
|
import { releaseCalendar } from "../../slices/studio/calendar.js";
|
|
17
|
-
import { studioPlaylistMax, studioUploadUrl, } from "../../slices/studio/model.js";
|
|
17
|
+
import { playlistUses, studioPlaylistMax, studioUploadUrl, } from "../../slices/studio/model.js";
|
|
18
18
|
import { packItem, uploadPack } from "../../slices/studio/pack.js";
|
|
19
19
|
import { channelPerformance } from "../../slices/studio/performance.js";
|
|
20
20
|
import { writeUploadPick } from "../../slices/studio/pick.js";
|
|
@@ -51,6 +51,8 @@ const playlistsBody = z.object({
|
|
|
51
51
|
.array(z.object({
|
|
52
52
|
name: z.string().max(studioPlaylistMax * 2),
|
|
53
53
|
byDefault: z.boolean(),
|
|
54
|
+
// Long videos, shorts or both (absent: both).
|
|
55
|
+
for: z.enum(playlistUses).optional(),
|
|
54
56
|
}))
|
|
55
57
|
.max(studioPlaylistsMax),
|
|
56
58
|
// A channel's own list; absent is the default every other channel uses.
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Slopify 3.8.5
|
|
2
|
+
|
|
3
|
+
Released 4 October 2026.
|
|
4
|
+
|
|
5
|
+
- **Playlists for long videos, shorts or both.** Each playlist in Settings → YouTube Studio → Playlists says what it takes: Videos and shorts, Long videos only, or Shorts only. A channel with a playlist of its own for shorts no longer gets its shorts added to the long videos' playlist.
|
|
6
|
+
|
|
7
|
+
## YouTube Studio extension (1.1.5)
|
|
8
|
+
|
|
9
|
+
- **Ad suitability is answered for you.** When an upload reaches Studio's Ad suitability questions, the extension ticks None of the above and presses Submit rating, then says so. If Studio's page doesn't show them as expected, it leaves them to you and says what to do. Download the extension again from Settings → YouTube Studio and reload it.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Slopify 3.8.6
|
|
2
|
+
|
|
3
|
+
Released 4 October 2026.
|
|
4
|
+
|
|
5
|
+
## YouTube Studio extension (1.1.6)
|
|
6
|
+
|
|
7
|
+
- **The schedule's date and time stick.** The extension typed the time while Studio was still taking the date, so the date was lost. Now it presses Enter on the date, waits until Studio shows it, and only then types the time and checks both. Dates and times are typed the way your Studio shows them ("6 Oct 2026" or "Oct 6, 2026", "17:00" or "5:00 PM").
|
|
8
|
+
- **Shorts are recorded once uploaded.** Studio shows a short's link as youtube.com/shorts/…, which the extension didn't recognise, so a short's upload was never recorded: Upload all didn't move on to the next short, and the related video wasn't set. Both kinds of link are read now.
|
|
9
|
+
- **The popup shows when each upload goes public**, not the time it should be uploaded by; one too close to going public still says late.
|
|
10
|
+
- A short's file size shows in MB, not "0.0 GB".
|
|
11
|
+
|
|
12
|
+
Download the extension again from Settings → YouTube Studio and reload it.
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"id": "3.8.6",
|
|
4
|
+
"title": "Slopify 3.8.6",
|
|
5
|
+
"version": "3.8.6",
|
|
6
|
+
"date": "2026-10-04"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "3.8.5",
|
|
10
|
+
"title": "Slopify 3.8.5",
|
|
11
|
+
"version": "3.8.5",
|
|
12
|
+
"date": "2026-10-04"
|
|
13
|
+
},
|
|
2
14
|
{
|
|
3
15
|
"id": "3.8.4",
|
|
4
16
|
"title": "Slopify 3.8.4",
|
|
@@ -11,6 +11,8 @@ export const studioPlaylistMax = 150;
|
|
|
11
11
|
export const studioAudience = "not_made_for_kids";
|
|
12
12
|
// Studio's upload page. It opens the upload dialog on the signed-in channel.
|
|
13
13
|
export const studioUploadUrl = "https://www.youtube.com/upload";
|
|
14
|
+
// What a playlist takes: every upload, only long videos, or only shorts.
|
|
15
|
+
export const playlistUses = ["all", "long", "shorts"];
|
|
14
16
|
// The steps in Studio's order, as the Prepare upload view lists them.
|
|
15
17
|
export const studioSteps = [
|
|
16
18
|
"video",
|
|
@@ -57,8 +57,14 @@ export function uploadPack(deps, projectId) {
|
|
|
57
57
|
const channelId = projectChannelId(deps.db, projectId);
|
|
58
58
|
// The channel's playlists (Settings → YouTube Studio), ticked as this project chose.
|
|
59
59
|
const playlistChoices = projectPlaylists(deps.db, projectId, channelId);
|
|
60
|
-
|
|
60
|
+
// The long video goes into the chosen playlists that take long videos, each short into those
|
|
61
|
+
// that take shorts.
|
|
62
|
+
const into = (kind) => playlistChoices
|
|
63
|
+
.filter((one) => one.chosen && (one.for === "all" || one.for === kind))
|
|
64
|
+
.map((one) => one.name);
|
|
65
|
+
const playlists = into("long");
|
|
61
66
|
const playlist = playlists[0] ?? null;
|
|
67
|
+
const shortPlaylists = into("shorts");
|
|
62
68
|
const missing = [];
|
|
63
69
|
// The channel's setting, then what the project narrates and shows (`disclosure.ts`).
|
|
64
70
|
const setting = channelById(deps.db, channelId)?.aiDisclosure ?? "auto";
|
|
@@ -202,8 +208,8 @@ export function uploadPack(deps, projectId) {
|
|
|
202
208
|
thumbnails: [],
|
|
203
209
|
audience: studioAudience,
|
|
204
210
|
alteredContent: disclosure("short"),
|
|
205
|
-
playlists,
|
|
206
|
-
playlist,
|
|
211
|
+
playlists: shortPlaylists,
|
|
212
|
+
playlist: shortPlaylists[0] ?? null,
|
|
207
213
|
...((at) => (at == null ? {} : { scheduleAt: at }))(schedule?.shortsAt[clip.number - 1]),
|
|
208
214
|
...(longVideo?.uploadState === "done" ? { relatedVideoId: longVideo.videoId } : {}),
|
|
209
215
|
});
|
|
@@ -217,7 +223,7 @@ export function uploadPack(deps, projectId) {
|
|
|
217
223
|
items,
|
|
218
224
|
...(schedule === undefined ? {} : { schedule }),
|
|
219
225
|
missing,
|
|
220
|
-
playlistChoices,
|
|
226
|
+
playlistChoices: playlistChoices.map(({ name, chosen }) => ({ name, chosen })),
|
|
221
227
|
...(uploadedClips > 0 ? { footage: { clips: uploadedClips, real: realFootage } } : {}),
|
|
222
228
|
},
|
|
223
229
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { readSetting, writeSetting } from "../settings/repo.js";
|
|
4
|
-
import { studioPlaylistMax } from "./model.js";
|
|
4
|
+
import { playlistUses, studioPlaylistMax, } from "./model.js";
|
|
5
5
|
// Rows of the key/value `settings` table. The playlists travel with a backup; the
|
|
6
6
|
// pairing stays on this machine (`slices/storage/portable.ts`): its token is what lets the
|
|
7
7
|
// browser extension read a project's upload pack.
|
|
@@ -26,6 +26,7 @@ export const studioPlaylistsMax = 20;
|
|
|
26
26
|
export const studioPlaylistSchema = z.object({
|
|
27
27
|
name: z.string().trim().min(1).max(studioPlaylistMax),
|
|
28
28
|
byDefault: z.boolean(),
|
|
29
|
+
for: z.enum(playlistUses).optional(),
|
|
29
30
|
});
|
|
30
31
|
// What a row holds: the list, or the one name a row held before lists.
|
|
31
32
|
export const storedPlaylistsSchema = z.union([
|
|
@@ -90,7 +91,12 @@ export function studioPlaylistsProblem(list) {
|
|
|
90
91
|
// the default again). Blank names are dropped.
|
|
91
92
|
export function saveStudioPlaylists(db, list, channelId) {
|
|
92
93
|
const value = list
|
|
93
|
-
.map((one) => ({
|
|
94
|
+
.map((one) => ({
|
|
95
|
+
name: one.name.trim(),
|
|
96
|
+
byDefault: one.byDefault,
|
|
97
|
+
// "all" is the default, so a list that never narrows stays as it was saved.
|
|
98
|
+
...(one.for === undefined || one.for === "all" ? {} : { for: one.for }),
|
|
99
|
+
}))
|
|
94
100
|
.filter((one) => one.name !== "");
|
|
95
101
|
const key = playlistKey(channelId);
|
|
96
102
|
if (value.length === 0) {
|
|
@@ -123,6 +129,7 @@ export function projectPlaylists(db, projectId, channelId) {
|
|
|
123
129
|
const own = projectChoices(db)[projectId];
|
|
124
130
|
return list.map((one) => ({
|
|
125
131
|
name: one.name,
|
|
132
|
+
for: one.for ?? "all",
|
|
126
133
|
chosen: own === undefined
|
|
127
134
|
? one.byDefault
|
|
128
135
|
: own.some((name) => name.toLowerCase() === one.name.toLowerCase()),
|