|
50 | 50 | Configuration: { |
51 | 51 | key: "Configuration", |
52 | 52 | openOnHover: "openOnHover", |
53 | | - defaultNoFlag: "defaultNoFlag", |
54 | | - defaultNoComment: "defaultNoComment", |
55 | | - defaultNoDownvote: "defaultNoDownvote", |
56 | | - defaultNoDelete: "defaultNoDelete", |
57 | 53 | watchFlags: "watchFlags", |
58 | 54 | watchQueues: "watchQueues", |
| 55 | + allowComments: "allowComments", |
59 | 56 | linkDisabled: "linkDisabled", |
60 | 57 | addAuthorName: "addAuthorName", |
61 | 58 | debug: "debug" |
|
72 | 69 | // cache-related helpers/values |
73 | 70 | // Some information from cache is stored on the variables as objects to make editing easier and simpler |
74 | 71 | // Each time something is changed in the variables, update* must also be called to save the changes to the cache |
75 | | - static config = _Store.get(Cached.Configuration.key) ?? {}; |
| 72 | + static config = _Store.get(Cached.Configuration.key) ?? { default: {} }; |
76 | 73 | static categories = _Store.get(Cached.FlagCategories) ?? []; |
77 | 74 | static flagTypes = _Store.get(Cached.FlagTypes) ?? []; |
78 | 75 | static updateConfiguration = () => _Store.set(Cached.Configuration.key, this.config); |
|
805 | 802 | 'a[href^="/users/"] div[title]' |
806 | 803 | )?.title ?? ""; |
807 | 804 | var popupDelay = 4 * 1e3; |
| 805 | + var configBoxes = [ |
| 806 | + ["Leave comment", "comment"], |
| 807 | + ["Flag", "flag"], |
| 808 | + ["Downvote", "downvote"], |
| 809 | + ["Delete", "delete"] |
| 810 | + ]; |
808 | 811 | var getIconPath = (name) => { |
809 | 812 | const element = GM_getResourceText(name); |
810 | 813 | const parsed = new DOMParser().parseFromString(element, "text/html"); |
|
1081 | 1084 | name; |
1082 | 1085 | id; |
1083 | 1086 | sanitisedName; |
1084 | | - cacheKey; |
1085 | 1087 | progress = null; |
1086 | 1088 | constructor(name, id) { |
1087 | 1089 | this.name = name; |
1088 | | - this.sanitisedName = this.name.replace(/\s/g, ""); |
1089 | | - this.cacheKey = `defaultNo${this.sanitisedName}`; |
| 1090 | + this.sanitisedName = this.name.replace(/\s/g, "").toLowerCase(); |
1090 | 1091 | this.id = id; |
1091 | 1092 | } |
1092 | 1093 | wasReported() { |
|
1704 | 1705 | } |
1705 | 1706 | getIcon() { |
1706 | 1707 | return this.createBotIcon( |
1707 | | - this.wasReported() ? `//logs.sobotics.org/Natty/${this.id}.html` : "" |
| 1708 | + this.wasReported() ? `//sentinel.sobotics.org/posts/aid/${this.id}` : "" |
1708 | 1709 | ); |
1709 | 1710 | } |
1710 | 1711 | getProgressMessage(feedback) { |
|
1975 | 1976 | const newEntries = Object.entries(this.reporters).filter(([name, instance]) => { |
1976 | 1977 | return instance.showOnPopover() && (!Page.isLqpReviewPage || (name !== "Smokey" || instance.wasReported())); |
1977 | 1978 | }).map(([, instance]) => { |
1978 | | - const botName = instance.sanitisedName.toLowerCase(); |
| 1979 | + const botName = instance.sanitisedName; |
1979 | 1980 | const botNameId = `advanced-flagging-send-feedback-to-${botName}-${this.id}`; |
1980 | | - const defaultNoCheck = Store.config[instance.cacheKey]; |
1981 | 1981 | const iconHtml = instance.getIcon().outerHTML; |
1982 | 1982 | const checkbox = { |
1983 | 1983 | // on post page, the id is not unique! |
|
1986 | 1986 | text: `${isFlagOrReview ? "" : "Feedback to"} ${iconHtml}`, |
1987 | 1987 | classes: [isFlagOrReview ? "mb4" : "fs-body1"] |
1988 | 1988 | }, |
1989 | | - selected: !defaultNoCheck |
| 1989 | + selected: Store.config.default[botName] |
1990 | 1990 | }; |
1991 | 1991 | return [instance.name, checkbox]; |
1992 | 1992 | }); |
|
2378 | 2378 |
|
2379 | 2379 | // src/modals/config.ts |
2380 | 2380 | function saveChanges() { |
2381 | | - document.querySelectorAll("#advanced-flagging-configuration-section-general > div > input").forEach((element) => { |
2382 | | - const id = element.id.split("-").pop(); |
| 2381 | + document.querySelectorAll("#advanced-flagging-configuration-section-general input").forEach((element) => { |
| 2382 | + const id = element.id; |
| 2383 | + const key = id.split("-").pop(); |
2383 | 2384 | const checked = element.checked; |
2384 | | - Store.config[id] = checked; |
| 2385 | + if (id.startsWith("advanced-flagging-default")) { |
| 2386 | + Store.config.default[key] = checked; |
| 2387 | + } else { |
| 2388 | + Store.config[key] = checked; |
| 2389 | + } |
2385 | 2390 | }); |
2386 | 2391 | Store.updateConfiguration(); |
2387 | 2392 | displayStacksToast("Configuration saved", "success"); |
|
2400 | 2405 | "advanced-flagging-configuration-modal", |
2401 | 2406 | { |
2402 | 2407 | title: { |
2403 | | - text: "AdvancedFlagging configuration" |
| 2408 | + text: "Advanced Flagging configuration" |
2404 | 2409 | }, |
2405 | 2410 | body: { |
2406 | 2411 | bodyHtml: getConfigModalBody() |
|
2460 | 2465 | { |
2461 | 2466 | text: "Open dropdown on hover", |
2462 | 2467 | configValue: Cached.Configuration.openOnHover, |
2463 | | - tooltipText: "Open the dropdown on hover and not on click" |
| 2468 | + description: "Opens the dropdown on hover and not on click" |
2464 | 2469 | }, |
2465 | 2470 | { |
2466 | 2471 | text: "Watch for manual flags", |
2467 | 2472 | configValue: Cached.Configuration.watchFlags, |
2468 | | - tooltipText: "Send feedback when a flag is raised manually" |
| 2473 | + description: "Sends feedback when a flag is raised manually" |
2469 | 2474 | }, |
2470 | 2475 | { |
2471 | 2476 | text: "Watch for queue responses", |
2472 | 2477 | configValue: Cached.Configuration.watchQueues, |
2473 | | - tooltipText: "Send feedback after a Looks OK or Recommend Deletion review in the Low Quality Answers queue" |
2474 | | - }, |
2475 | | - { |
2476 | | - text: "Disable AdvancedFlagging link", |
2477 | | - configValue: Cached.Configuration.linkDisabled |
2478 | | - }, |
2479 | | - { |
2480 | | - text: "Uncheck 'Leave comment' by default", |
2481 | | - configValue: Cached.Configuration.defaultNoComment |
2482 | | - }, |
2483 | | - { |
2484 | | - text: "Uncheck 'Flag' by default", |
2485 | | - configValue: Cached.Configuration.defaultNoFlag |
2486 | | - }, |
2487 | | - { |
2488 | | - text: "Uncheck 'Downvote' by default", |
2489 | | - configValue: Cached.Configuration.defaultNoDownvote |
2490 | | - }, |
2491 | | - { |
2492 | | - text: "Uncheck 'Delete' by default", |
2493 | | - configValue: Cached.Configuration.defaultNoDelete |
| 2478 | + description: "Sends feedback after a Looks OK or Recommend Deletion review in the Low Quality Answers queue" |
2494 | 2479 | }, |
2495 | 2480 | { |
2496 | 2481 | text: "Add author's name before comments", |
2497 | 2482 | configValue: Cached.Configuration.addAuthorName, |
2498 | | - tooltipText: "Add the author's name before every comment to make them friendlier" |
2499 | | - }, |
2500 | | - { |
2501 | | - text: "Don't send feedback to Smokey by default", |
2502 | | - configValue: new Reporter("Smokey", 0).cacheKey |
| 2483 | + description: "Adds the author's name before every comment to make it friendlier" |
2503 | 2484 | }, |
2504 | 2485 | { |
2505 | | - text: "Don't send feedback to Natty by default", |
2506 | | - configValue: new Reporter("Natty", 0).cacheKey |
| 2486 | + text: 'Enable "Leave comment" on all Stack Exchange sites', |
| 2487 | + configValue: Cached.Configuration.allowComments, |
| 2488 | + description: 'Shows the "Leave comment" checkbox and the answer-related dropdown options on every Stack Exchange site' |
2507 | 2489 | }, |
2508 | 2490 | { |
2509 | | - text: "Don't send feedback to Guttenberg by default", |
2510 | | - configValue: new Reporter("Guttenberg", 0).cacheKey |
2511 | | - }, |
2512 | | - { |
2513 | | - text: "Don't send feedback to Generic Bot by default", |
2514 | | - configValue: new Reporter("Generic Bot", 0).cacheKey |
| 2491 | + text: "Disable Advanced Flagging link", |
| 2492 | + configValue: Cached.Configuration.linkDisabled |
2515 | 2493 | }, |
2516 | 2494 | { |
2517 | 2495 | text: "Enable dry-run mode", |
2518 | 2496 | configValue: Cached.Configuration.debug |
2519 | 2497 | } |
2520 | | - ].map(({ text, configValue, tooltipText }) => { |
| 2498 | + ].map(({ text, configValue, description }) => { |
2521 | 2499 | const selected = Store.config[configValue]; |
2522 | 2500 | return { |
2523 | 2501 | id: `advanced-flagging-${configValue}`, |
2524 | 2502 | labelConfig: { |
2525 | 2503 | text, |
2526 | | - description: tooltipText |
| 2504 | + description |
| 2505 | + }, |
| 2506 | + selected |
| 2507 | + }; |
| 2508 | + }); |
| 2509 | + const botBoxes = ["Smokey", "Natty", "Generic Bot", "Guttenberg"].map((name) => { |
| 2510 | + const reporter = new Reporter(name, 0); |
| 2511 | + const sanitised = reporter.sanitisedName; |
| 2512 | + const selected = Store.config.default[sanitised]; |
| 2513 | + return { |
| 2514 | + id: `advanced-flagging-default-${sanitised}`, |
| 2515 | + labelConfig: { |
| 2516 | + text: name |
2527 | 2517 | }, |
2528 | 2518 | selected |
2529 | 2519 | }; |
2530 | 2520 | }); |
| 2521 | + const [defaultFeedback] = checkbox_exports.makeStacksCheckboxes( |
| 2522 | + botBoxes, |
| 2523 | + { |
| 2524 | + horizontal: true, |
| 2525 | + classes: ["fs-body2"] |
| 2526 | + } |
| 2527 | + ); |
| 2528 | + const botDescription = document.createElement("div"); |
| 2529 | + botDescription.classList.add("flex--item"); |
| 2530 | + botDescription.innerText = "Send feedback by default to:"; |
| 2531 | + defaultFeedback.prepend(botDescription); |
| 2532 | + const optionBoxes = configBoxes.map(([name, sanitised]) => { |
| 2533 | + const selected = Store.config.default[sanitised]; |
| 2534 | + return { |
| 2535 | + id: `advanced-flagging-default-${sanitised}`, |
| 2536 | + labelConfig: { |
| 2537 | + text: name |
| 2538 | + }, |
| 2539 | + selected |
| 2540 | + }; |
| 2541 | + }); |
| 2542 | + const [defaultCheck] = checkbox_exports.makeStacksCheckboxes( |
| 2543 | + optionBoxes, |
| 2544 | + { |
| 2545 | + horizontal: true, |
| 2546 | + classes: ["fs-body2"] |
| 2547 | + } |
| 2548 | + ); |
| 2549 | + const optionDescription = document.createElement("div"); |
| 2550 | + optionDescription.classList.add("flex--item"); |
| 2551 | + optionDescription.innerText = "Check the following by default:"; |
| 2552 | + defaultCheck.prepend(optionDescription); |
2531 | 2553 | const [fieldset] = checkbox_exports.makeStacksCheckboxes(checkboxes); |
2532 | 2554 | fieldset.id = "advanced-flagging-configuration-section-general"; |
| 2555 | + fieldset.append(defaultFeedback, defaultCheck); |
2533 | 2556 | return fieldset; |
2534 | 2557 | } |
2535 | 2558 | function getAdminConfigItems() { |
|
3186 | 3209 | "advanced-flagging-comments-modal", |
3187 | 3210 | { |
3188 | 3211 | title: { |
3189 | | - text: "AdvancedFlagging: edit comments and flags" |
| 3212 | + text: "Advanced Flagging: edit comments and flags" |
3190 | 3213 | }, |
3191 | 3214 | body: { |
3192 | 3215 | bodyHtml: getCommentsModalBody() |
|
3288 | 3311 | cachedFlag.reportType = "PlagiarizedContent" /* Plagiarism */; |
3289 | 3312 | }); |
3290 | 3313 | Store.updateFlagTypes(); |
3291 | | - if (!("defaultNoDelete" in Store.config)) { |
3292 | | - Store.config.defaultNoDelete = true; |
| 3314 | + if (!(Cached.Configuration.allowComments in Store.config)) { |
| 3315 | + Store.config.allowComments = false; |
| 3316 | + Store.updateConfiguration(); |
| 3317 | + } |
| 3318 | + if ("defaultNoSmokey" in Store.config) { |
| 3319 | + Store.config.default = {}; |
| 3320 | + [ |
| 3321 | + ["defaultNoComment", "comment"], |
| 3322 | + ["defaultNoFlag", "flag"], |
| 3323 | + ["defaultNoDownvote", "downvote"], |
| 3324 | + ["defaultNoSmokey", "smokey"], |
| 3325 | + ["defaultNoNatty", "natty"], |
| 3326 | + ["defaultNoGuttenberg", "guttenberg"], |
| 3327 | + ["defaultNoGenericBot", "genericbot"], |
| 3328 | + ["defaultNoDelete", "delete"] |
| 3329 | + ].forEach(([oldName, newName]) => { |
| 3330 | + Store.config.default[newName] = !Store.config[oldName]; |
| 3331 | + delete Store.config[oldName]; |
| 3332 | + }); |
3293 | 3333 | Store.updateConfiguration(); |
3294 | 3334 | } |
3295 | 3335 | } |
|
3318 | 3358 | ); |
3319 | 3359 | if (!propertyDoesNotExist) return; |
3320 | 3360 | displayStacksToast( |
3321 | | - "Please set up AdvancedFlagging before continuing.", |
| 3361 | + "Please set up Advanced Flagging before continuing.", |
3322 | 3362 | "info", |
3323 | 3363 | true |
3324 | 3364 | ); |
3325 | | - setTimeout(() => { |
3326 | | - Stacks.showModal(configModal); |
3327 | | - const checkbox = document.querySelector( |
3328 | | - "#advanced-flagging-defaultNoDownvote" |
3329 | | - ); |
3330 | | - checkbox.checked = true; |
3331 | | - }); |
| 3365 | + setTimeout(() => Stacks.showModal(configModal)); |
3332 | 3366 | } |
3333 | 3367 |
|
3334 | 3368 | // src/popover.ts |
|
3375 | 3409 | const { copypastorId, repost, targetUrl } = copypastor ?? {}; |
3376 | 3410 | const categories = Store.categories.filter((item) => item.appliesTo?.includes(this.post.type)).map((item) => ({ ...item, FlagTypes: [] })); |
3377 | 3411 | Store.flagTypes.filter(({ reportType, id, belongsTo, enabled }) => { |
| 3412 | + if (belongsTo === "Answer-related" && (Page.isStackOverflow || Store.config.allowComments)) return true; |
3378 | 3413 | const isGuttenbergItem = isSpecialFlag(reportType, false); |
3379 | 3414 | const showGutReport = Boolean(copypastorId) && (id === 4 ? repost : !repost); |
3380 | 3415 | const showOnSo = ["Red flags", "General"].includes(belongsTo) || Page.isStackOverflow; |
|
3415 | 3450 | // Section #2: Leave comment, Flag, Downvote |
3416 | 3451 | getOptionsRow() { |
3417 | 3452 | const comments = this.post.element.querySelector(".comment-body"); |
3418 | | - const config = [ |
3419 | | - ["Leave comment", Cached.Configuration.defaultNoComment], |
3420 | | - ["Flag", Cached.Configuration.defaultNoFlag], |
3421 | | - ["Downvote", Cached.Configuration.defaultNoDownvote], |
3422 | | - ["Delete", Cached.Configuration.defaultNoDelete] |
3423 | | - ]; |
3424 | | - return config.filter(([text]) => { |
3425 | | - if (text === "Leave comment") return Page.isStackOverflow; |
| 3453 | + return configBoxes.filter(([text]) => { |
| 3454 | + if (text === "Leave comment") return Store.config.allowComments || Page.isStackOverflow; |
3426 | 3455 | else if (text === "Delete") return this.post.canDelete(true); |
3427 | 3456 | return true; |
3428 | 3457 | }).map(([text, cacheKey]) => { |
3429 | | - const uncheck = Store.config[cacheKey] || text === "Leave comment" && comments; |
| 3458 | + const selected = Store.config.default[cacheKey] && (text === "Leave comment" ? Boolean(comments) : true); |
3430 | 3459 | const idified = text.toLowerCase().replace(" ", "-"); |
3431 | 3460 | const id = `advanced-flagging-${idified}-checkbox-${this.post.id}`; |
3432 | 3461 | return { |
|
3436 | 3465 | text, |
3437 | 3466 | classes: ["pt1", "fs-body1"] |
3438 | 3467 | }, |
3439 | | - // !uncheck => whether the checkbox should be checked :) |
3440 | | - selected: !uncheck |
| 3468 | + selected |
3441 | 3469 | } |
3442 | 3470 | }; |
3443 | 3471 | }); |
|
3468 | 3496 | const flagName = getFlagToRaise(reportType, this.post.qualifiesForVlq()); |
3469 | 3497 | let reportTypeHuman = reportType === "NoFlag" || !this.post.deleted ? getHumanFromDisplayName(flagName) : ""; |
3470 | 3498 | if (reportType !== flagName) { |
3471 | | - reportTypeHuman += " (VLQ criteria weren't met)"; |
| 3499 | + reportTypeHuman += " (VLQ criteria aren't met)"; |
3472 | 3500 | } |
3473 | 3501 | const popoverParent = document.createElement("div"); |
3474 | 3502 | Object.entries({ |
|
3847 | 3875 | } |
3848 | 3876 | var isDone = false; |
3849 | 3877 | function Setup() { |
| 3878 | + setupConfiguration(); |
3850 | 3879 | void Promise.all([ |
3851 | 3880 | MetaSmokeAPI.setup(), |
3852 | 3881 | MetaSmokeAPI.queryMetaSmokeInternal(), |
|
3855 | 3884 | ]).then(() => { |
3856 | 3885 | setupPostPage(); |
3857 | 3886 | setupStyles(); |
3858 | | - setupConfiguration(); |
3859 | 3887 | addXHRListener(() => { |
3860 | 3888 | setupPostPage(); |
3861 | 3889 | setTimeout(setupPostPage, 55); |
|
0 commit comments