Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

firefox-scripts dont work on 136.0b2 #341

Open
Ranamzes opened this issue Feb 6, 2025 · 4 comments
Open

firefox-scripts dont work on 136.0b2 #341

Ranamzes opened this issue Feb 6, 2025 · 4 comments

Comments

@Ranamzes
Copy link

Ranamzes commented Feb 6, 2025

In the latest 136.0b2 update, firefox-scripts stopped working. I tried installing again with file replacement.

@Zhiro90
Copy link

Zhiro90 commented Feb 6, 2025

se here: #333
using the fixes proposed in the several issues, some are working: #336

FF Nightly 136a With the fixes mentioned in the thread, got these scripts working as of feb 3:

Supposed to work:

  • Tabmixplus: Has been updated, haven't updated it yet
  • Styloaix: It's mentioned in the linked issues that it's partially working, haven't tinkered with it again yet

These scripts are still broken:

  • Mouse Gestures
  • Enter Selects
  • Private Tab

if a script isn't listed here is because I don't use it.

On the other hand All legacy extensions that I use (save file to, rehost image, pilfer, norwell history, downthemall, dorando keyconfig and backtrack tab history) have been disabled with no option to enable, about:config option to ignore signatures is greyed out, would need to wait for extensions updates

@srjjgm
Copy link

srjjgm commented Feb 7, 2025

StyloaiX works partially. The browser can "read" the codes and apply them, but it's not possible to activate, deactivate, create or edit styles.

@117649
Copy link

117649 commented Feb 7, 2025

StyloaiX works partially. The browser can "read" the codes and apply them, but it's not possible to activate, deactivate, create or edit styles.

Try edit files in \utils\styloaix

autocomplete.js

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

const AutocompletePopup = require('devtools/client/shared/autocomplete-popup');

let loader;
try {
  ({ loader } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs'));
} catch (e) {
  // tb91
  ({ loader } = ChromeUtils.importESModule('resource://devtools/shared/Loader.sys.mjs'));
}

loader.lazyRequireGetter(
  this,
  "KeyCodes",
  "devtools/client/shared/keycodes",
  true
);
loader.lazyRequireGetter(
  this,
  "CSSCompleter",
  "devtools/client/shared/sourceeditor/css-autocompleter"
);

const autocompleteMap = new WeakMap();

/**
 * Prepares an editor instance for autocompletion.
 */
function initializeAutoCompletion(ctx, options = {}) {
  const { cm, ed, Editor } = ctx;
  if (autocompleteMap.has(ed)) {
    return;
  }

  const win = ed.container.contentWindow.wrappedJSObject;
  const { CodeMirror } = win;

  let completer = null;
  const autocompleteKey =
    "Ctrl-" + Editor.keyFor("autocompletion", { noaccel: true });
  if (ed.config.mode == Editor.modes.css) {
    completer = new CSSCompleter({
      walker: options.walker,
      cssProperties: options.cssProperties,
      maxEntries: 1000,
    });
  }

  function insertSelectedPopupItem() {
    const autocompleteState = autocompleteMap.get(ed);
    if (!popup || !popup.isOpen || !autocompleteState) {
      return false;
    }

    if (!autocompleteState.suggestionInsertedOnce && popup.selectedItem) {
      autocompleteMap.get(ed).insertingSuggestion = true;
      insertPopupItem(ed, popup.selectedItem);
    }

    popup.once("popup-closed", () => {
      // This event is used in tests.
      ed.emit("popup-hidden");
    });
    popup.hidePopup();
    return true;
  }

  // Give each popup a new name to avoid sharing the elements.

  let popup = new AutocompletePopup(win.parent.document, {
    position: "bottom",
    autoSelect: true,
    onClick: insertSelectedPopupItem,
  });

  const cycle = reverse => {
    if (popup?.isOpen) {
      // eslint-disable-next-line mozilla/no-compare-against-boolean-literals
      cycleSuggestions(ed, reverse == true);
      return null;
    }

    return CodeMirror.Pass;
  };

  let keyMap = {
    Tab: cycle,
    Down: cycle,
    "Shift-Tab": cycle.bind(null, true),
    Up: cycle.bind(null, true),
    Enter: () => {
      const wasHandled = insertSelectedPopupItem();
      return wasHandled ? true : CodeMirror.Pass;
    },
  };

  const autoCompleteCallback = autoComplete.bind(null, ctx);
  const keypressCallback = onEditorKeypress.bind(null, ctx);
  keyMap[autocompleteKey] = autoCompleteCallback;
  cm.addKeyMap(keyMap);

  cm.on("keydown", keypressCallback);
  ed.on("change", autoCompleteCallback);
  ed.on("destroy", destroy);

  function destroy() {
    ed.off("destroy", destroy);
    cm.off("keydown", keypressCallback);
    ed.off("change", autoCompleteCallback);
    cm.removeKeyMap(keyMap);
    popup.destroy();
    keyMap = popup = completer = null;
    autocompleteMap.delete(ed);
  }

  autocompleteMap.set(ed, {
    popup: popup,
    completer: completer,
    keyMap: keyMap,
    destroy: destroy,
    insertingSuggestion: false,
    suggestionInsertedOnce: false,
  });
}

/**
 * Provides suggestions to autocomplete the current token/word being typed.
 */
function autoComplete({ ed, cm }) {
  const autocompleteOpts = autocompleteMap.get(ed);
  const { completer, popup } = autocompleteOpts;
  if (
    !completer ||
    autocompleteOpts.insertingSuggestion ||
    autocompleteOpts.doNotAutocomplete
  ) {
    autocompleteOpts.insertingSuggestion = false;
    return;
  }
  const cur = ed.getCursor();
  completer
    .complete(cm.getRange({ line: 0, ch: 0 }, cur), cur)
    .then(suggestions => {
      if (
        !suggestions ||
        !suggestions.length ||
        suggestions[0].preLabel == null
      ) {
        autocompleteOpts.suggestionInsertedOnce = false;
        popup.once("popup-closed", () => {
          // This event is used in tests.
          ed.emit("after-suggest");
        });
        popup.hidePopup();
        return;
      }
      // The cursor is at the end of the currently entered part of the token,
      // like "backgr|" but we need to open the popup at the beginning of the
      // character "b". Thus we need to calculate the width of the entered part
      // of the token ("backgr" here).

      const cursorElement = cm.display.cursorDiv.querySelector(
        ".CodeMirror-cursor"
      );
      const left = suggestions[0].preLabel.length * cm.defaultCharWidth();
      popup.hidePopup();
      popup.setItems(suggestions);

      popup.once("popup-opened", () => {
        // This event is used in tests.
        ed.emit("after-suggest");
      });
      popup.openPopup(cursorElement, -1 * left, 0);
      autocompleteOpts.suggestionInsertedOnce = false;
    })
    .catch(console.error);
}

/**
 * Inserts a popup item into the current cursor location
 * in the editor.
 */
function insertPopupItem(ed, popupItem) {
  const { preLabel, text } = popupItem;
  const cur = ed.getCursor();
  const textBeforeCursor = ed.getText(cur.line).substring(0, cur.ch);
  const backwardsTextBeforeCursor = textBeforeCursor
    .split("")
    .reverse()
    .join("");
  const backwardsPreLabel = preLabel
    .split("")
    .reverse()
    .join("");

  // If there is additional text in the preLabel vs the line, then
  // just insert the entire autocomplete text.  An example:
  // if you type 'a' and select '#about' from the autocomplete menu,
  // then the final text needs to the end up as '#about'.
  if (backwardsPreLabel.indexOf(backwardsTextBeforeCursor) === 0) {
    ed.replaceText(text, { line: cur.line, ch: 0 }, cur);
  } else {
    ed.replaceText(text.slice(preLabel.length), cur, cur);
  }
}

/**
 * Cycles through provided suggestions by the popup in a top to bottom manner
 * when `reverse` is not true. Opposite otherwise.
 */
function cycleSuggestions(ed, reverse) {
  const autocompleteOpts = autocompleteMap.get(ed);
  const { popup } = autocompleteOpts;
  const cur = ed.getCursor();
  autocompleteOpts.insertingSuggestion = true;
  if (!autocompleteOpts.suggestionInsertedOnce) {
    autocompleteOpts.suggestionInsertedOnce = true;
    let firstItem;
    if (reverse) {
      firstItem = popup.getItemAtIndex(popup.itemCount - 1);
      popup.selectPreviousItem();
    } else {
      firstItem = popup.getItemAtIndex(0);
      if (firstItem.label == firstItem.preLabel && popup.itemCount > 1) {
        firstItem = popup.getItemAtIndex(1);
        popup.selectNextItem();
      }
    }
    if (popup.itemCount == 1) {
      popup.hidePopup();
    }
    insertPopupItem(ed, firstItem);
  } else {
    const fromCur = {
      line: cur.line,
      ch: cur.ch - popup.selectedItem.text.length,
    };
    if (reverse) {
      popup.selectPreviousItem();
    } else {
      popup.selectNextItem();
    }
    ed.replaceText(popup.selectedItem.text, fromCur, cur);
  }
  // This event is used in tests.
  ed.emit("suggestion-entered");
}

/**
 * onkeydown handler for the editor instance to prevent autocompleting on some
 * keypresses.
 */
function onEditorKeypress({ ed, Editor }, cm, event) {
  const autocompleteOpts = autocompleteMap.get(ed);

  // Do not try to autocomplete with multiple selections.
  if (ed.hasMultipleSelections()) {
    autocompleteOpts.doNotAutocomplete = true;
    autocompleteOpts.popup.hidePopup();
    return;
  }

  if (
    (event.ctrlKey || event.metaKey) &&
    event.keyCode == KeyCodes.DOM_VK_SPACE
  ) {
    // When Ctrl/Cmd + Space is pressed, two simultaneous keypresses are emitted
    // first one for just the Ctrl/Cmd and second one for combo. The first one
    // leave the autocompleteOpts.doNotAutocomplete as true, so we have to make
    // it false
    autocompleteOpts.doNotAutocomplete = false;
    return;
  }

  if (event.ctrlKey || event.metaKey || event.altKey) {
    autocompleteOpts.doNotAutocomplete = true;
    autocompleteOpts.popup.hidePopup();
    return;
  }

  switch (event.keyCode) {
    case KeyCodes.DOM_VK_RETURN:
      autocompleteOpts.doNotAutocomplete = true;
      break;
    case KeyCodes.DOM_VK_ESCAPE:
      if (autocompleteOpts.popup.isOpen) {
        // Prevent the Console input to open, but still remove the autocomplete popup.
        autocompleteOpts.doNotAutocomplete = true;
        autocompleteOpts.popup.hidePopup();
        event.preventDefault();
      }
      break;
    case KeyCodes.DOM_VK_LEFT:
    case KeyCodes.DOM_VK_RIGHT:
    case KeyCodes.DOM_VK_HOME:
    case KeyCodes.DOM_VK_END:
      autocompleteOpts.doNotAutocomplete = true;
      autocompleteOpts.popup.hidePopup();
      break;
    case KeyCodes.DOM_VK_BACK_SPACE:
    case KeyCodes.DOM_VK_DELETE:
      if (ed.config.mode == Editor.modes.css) {
        autocompleteOpts.completer.invalidateCache(ed.getCursor().line);
      }
      autocompleteOpts.doNotAutocomplete = true;
      autocompleteOpts.popup.hidePopup();
      break;
    default:
      autocompleteOpts.doNotAutocomplete = false;
  }
}

// Export functions

exports.initializeAutoCompletion = initializeAutoCompletion;

edit.js

const { NetUtil } = ChromeUtils.importESModule('resource://gre/modules/NetUtil.sys.mjs');

const { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs');

docShell.cssErrorReportingEnabled = true;

function require_mini (m) {
  let scope = {
    exports: {}
  };
  Services.scriptloader.loadSubScript('chrome://' + m + '.js', scope);
  return scope.exports;
};

let url;
let type;
let id;
let style;

if (isChromeWindow) {
  let params = window.arguments[0];
  url = params.url;
  type = params.type;
  id = params.id;
} else {
  let params = new URLSearchParams(location.search);
  url = params.get('url');
  type = params.get('type');
  id = params.get('id');
}

origin = 1;
let lastOrigin;
let unsaved = false;
let previewCode;
let previewOrigin;
let previewActive = false;
let isInstantPreview;
let isInstantCheck;
let timeoutRunning = false;
let interval;
let nameE;
let initialCode = '';
let sourceEditor;

function init () {
  if (id)
    style = UC.styloaix.styles.get(id);
  if (style) {
    origin = style.type;
    readFile(style.url, initEditor);
  } else {
    if (url)
      initialCode = '@-moz-document ' + type + '("' + url + '") {\n\n\n}';
    initEditor();
  }

  nameE = document.getElementById('name');
  nameE.value = style?.name || '';
  updateTitle();
  nameE.addEventListener('input', function () {
    unsaved = true;
    toggleUI('save-button', true);
  });

  document.getElementById('origin').value = origin;

  document.getElementById('errors').addEventListener('click', function (e) {
    if (e.target == this)
      this.style.display = 'none';
  });

  isInstantPreview = xPref.get(UC.styloaix.PREF_INSTANTPREVIEW);
  document.getElementById('instant-preview').checked = isInstantPreview;
  isInstantCheck = xPref.get(UC.styloaix.PREF_INSTANTCHECK);
  document.getElementById('instant-check').checked = isInstantCheck;
  if (style?.enabled === false)
    toggleUI('preview-button', true);
  interval = xPref.get(UC.styloaix.PREF_INSTANTINTERVAL);
  xPref.addListener(UC.styloaix.PREF_INSTANTINTERVAL, function (ms) {
    interval = ms;
  });
}

function initEditor () {
  const Editor = require('devtools/client/shared/sourceeditor/editor');

  const extraKeys = {
    [Editor.accel('S')]: save,
    'F3': 'findNext',
    'Shift-F3': 'findPrev'
  };

  const lineWrapping = xPref.get(UC.styloaix.PREF_LINEWRAPPING);
  document.getElementById('wrap-lines').checked = lineWrapping;

  sourceEditor = new Editor({
    mode: Editor.modes.css,
    contextMenu: 'sourceEditorContextMenu',
    extraKeys: extraKeys,
    lineNumbers: true,
    lineWrapping: lineWrapping,
    value: initialCode,
    maxHighlightLength: 10000
  });

  // https://searchfox.org/mozilla-central/source/devtools/client/shared/test/shared-head.js#2284-2295
  function getClientCssProperties() {
    const {
      generateCssProperties,
    } = require('resource://devtools/server/actors/css-properties.js');
    const {
      CssProperties,
      normalizeCssData,
    } = require('resource://devtools/client/fronts/css-properties.js');
    return new CssProperties(
      normalizeCssData({ properties: generateCssProperties(document) })
    );
  }

  sourceEditor.setupAutoCompletion = function () {
    this.extend(require_mini('userchromejs/content/styloaix/autocomplete'));
    this.initializeAutoCompletion({ cssProperties: getClientCssProperties() });
  };

  document.getElementById('editor').selectedIndex = 1;

  sourceEditor.appendTo(document.getElementById('sourceeditor')).then(function () {
    sourceEditor.insertCommandsController();
    sourceEditor.focus();
    if (isInstantCheck)
      checkForErrors();
  });

  sourceEditor.on('change', function () {
    changed();
    if (!isInstantCheck)
      toggleUI('check-for-errors-button', true);
  });
}

function readFile (url, fun) {
  NetUtil.asyncFetch(
    {
      uri: url,
      loadingNode: document,
      securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT || Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS,
      contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
    },
    async function (stream) {
      const bstream = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
      bstream.setInputStream(stream);

      try {
        initialCode = bstream.readBytes(bstream.available());
      } catch {}

      stream.close();

      try {
        const converter = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Ci.nsIScriptableUnicodeConverter);
        converter.charset = 'utf-8';
        initialCode = converter.ConvertToUnicode(initialCode);
      } catch {}

      fun?.();
    }
  );
}

function changed () {
  if ((isInstantPreview || isInstantCheck) && !timeoutRunning)
    instantTimeout();

  unsaved = true;
  toggleUI('save-button', true);
  if (!isInstantPreview)
    toggleUI('preview-button', true);
}

function instantTimeout () {
  timeoutRunning = true;
  setTimeout(() => {
    if (isInstantPreview) {
      processPreview();
      toggleUI('preview-button', false);

      if (origin === _uc.sss.AGENT_SHEET || lastOrigin === _uc.sss.AGENT_SHEET) {
        lastOrigin = origin;
        UC.styloaix.forceRefresh();
      }
    }
    if (isInstantCheck)
      checkForErrors();
    timeoutRunning = false;
  }, interval)
}

function save () {
  if (!nameE.value)
    return alert('Style name must not be empty.');

  if (style)
    style.unregister();

  const finalTitle = nameE.value + (origin == 0 ? '.as' : origin == 1 ? '.us' : '') + '.css';
  const file = UC.styloaix.CSSDIR.clone();
  file.append(finalTitle);
  if (!file.exists())
    file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644/*FileUtils.PERMS_FILE*/);

  const ostream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
  ostream.init(file, -1, -1, 0);

  const istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
  istream.setUTF8Data(codeElementWrapper.value);

  NetUtil.asyncCopy(istream, ostream, function (aResult) {
    if (Components.isSuccessCode(aResult)) {
      const enabled = style ? style.enabled : true;

      if (style && finalTitle != style.fullName) {
        const oldFile = UC.styloaix.CSSDIR.clone()
        oldFile.append(style.fullName);
        oldFile.remove(false);
        UC.styloaix.styles.delete(style.fullName);
        if (!enabled) {
          UC.styloaix.disabledStyles.add(finalTitle);
          UC.styloaix.disabledStyles.delete(oldFile.leafName);
        }
      }

      style = new UC.styloaix.UserStyle(file);
      style.enabled = enabled;
      updateTitle();
      UC.styloaix.styles.set(style.fullName, style);
      if (UC.styloaix.enabled && enabled) {
        style.register();
        toggleUI('preview-button', false);
        if (previewActive) {
          _uc.sss.unregisterSheet(previewCode, previewOrigin);
          previewActive = false;
          if (origin === _uc.sss.AGENT_SHEET || lastOrigin === _uc.sss.AGENT_SHEET)
            UC.styloaix.forceRefresh();
        }
      }

      unsaved = false;

      toggleUI('save-button', false);
    } else {
      alert('Error!');
    }
  })

  sourceEditor.focus();
}

function updateTitle () {
  document.title = (style?.fullName || 'New Style') + ' - StyloaiX Editor';
}

function toggleUI (id, state) {
  document.getElementById(id).disabled = !state;
}

function processPreview () {
  let lastPreviewCode = previewCode;
  let lastpreviewOrigin = previewOrigin;

  previewCode = Services.io.newURI('data:text/css;charset=UTF-8,' + encodeURIComponent(codeElementWrapper.value));
  previewOrigin = origin;
  _uc.sss.loadAndRegisterSheet(previewCode, previewOrigin);

  if (previewActive)
    _uc.sss.unregisterSheet(lastPreviewCode, lastpreviewOrigin);
  else if (style?.enabled)
    style.unregister();

  previewActive = true;
}

function preview () {
  processPreview();

  if (origin === _uc.sss.AGENT_SHEET || lastOrigin === _uc.sss.AGENT_SHEET) {
    lastOrigin = origin;
    UC.styloaix.forceRefresh();
  }

  checkForErrors();
  toggleUI('preview-button', false);
  sourceEditor.focus();
}

function checkForErrors () {
  const errors = document.getElementById('errors');
  errors.style.display = 'none';

  while (errors.hasChildNodes())
    errors.lastChild.remove();

  let count = 0;

  const errorListener = {
    observe: (message) => {
      if (!count)
        errors.style.display = 'block';

      const error = message.QueryInterface(Ci.nsIScriptError);
      const errMsg = error.lineNumber + ':' + error.columnNumber + ' - ' + error.errorMessage;

      const label = document.createElement('label');
      label.appendChild(document.createTextNode(errMsg));
      label.addEventListener('click', function () {
        goToLine(error.lineNumber, error.columnNumber);
      });
      errors.appendChild(label);
      errors.appendChild(document.createElement('br'));
      count++;

      if (count == 10) {
        errors.appendChild(document.createTextNode('...'));
        Services.console.unregisterListener(this);
      }
    }
  }

  Services.console.registerListener(errorListener);

  const styleEl = document.createElement('style');
  styleEl.appendChild(document.createTextNode(codeElementWrapper.value));
  document.documentElement.appendChild(styleEl);
  styleEl.remove();

  setTimeout(() => {
    if (count < 10)
      Services.console.unregisterListener(errorListener);
  });

  toggleUI('check-for-errors-button', false);
  sourceEditor.focus();
}

function goToLine (line, col) {
  sourceEditor.focus();
  sourceEditor.setCursor({line: line - 1, ch: col});
}

function insertCodeAtStart (snippet) {
  let position = codeElementWrapper.value.indexOf(snippet);
  if (position == -1) {
    codeElementWrapper.value = snippet + '\n' + codeElementWrapper.value;
    position = 0;
  }
  const positionEnd = position + snippet.length;

  codeElementWrapper.setSelectionRange(positionEnd, positionEnd);
  sourceEditor.focus();
}

function insertCodeAtCaret (snippet) {
  const selectionStart = codeElementWrapper.selectionStart;
  const selectionEnd = selectionStart + snippet.length;
  codeElementWrapper.value = codeElementWrapper.value.substring(0, codeElementWrapper.selectionStart) + snippet + codeElementWrapper.value.substring(codeElementWrapper.selectionEnd, codeElementWrapper.value.length);
  codeElementWrapper.setSelectionRange(selectionEnd, selectionEnd);
  sourceEditor.focus();
}

function changeWordWrap (bool, persist) {
  if (persist)
    xPref.set(UC.styloaix.PREF_LINEWRAPPING, bool);
  sourceEditor.setOption('lineWrapping', bool);
  sourceEditor.focus();
}

function instantPreview (bool, persist) {
  if (persist)
    xPref.set(UC.styloaix.PREF_INSTANTPREVIEW, bool);
  isInstantPreview = bool
  if (isInstantPreview && !timeoutRunning)
    instantTimeout();

  sourceEditor.focus();
}

function instantCheck (bool, persist) {
  if (persist)
    xPref.set(UC.styloaix.PREF_INSTANTCHECK, bool);
  isInstantCheck = bool
  if (isInstantCheck && !timeoutRunning)
    instantTimeout();

  sourceEditor.focus();
}

function insertDataURI() {
  const fp = Cc['@mozilla.org/filepicker;1'].createInstance(Ci.nsIFilePicker);
  fp.init(window, 'Choose File…', Ci.nsIFilePicker.modeOpen);
  fp.open(res => {
    if (res != Ci.nsIFilePicker.returnOK)
      return;

    const contentType = Cc['@mozilla.org/mime;1'].getService(Ci.nsIMIMEService).getTypeFromFile(fp.file);
    const inputStream = Cc['@mozilla.org/network/file-input-stream;1'].createInstance(Ci.nsIFileInputStream);
    inputStream.init(fp.file, parseInt('01', 16), parseInt('0600', 8), 0);
    const stream = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
    stream.setInputStream(inputStream);
    const encoded = btoa(stream.readBytes(stream.available()));
    stream.close();
    inputStream.close();
    insertCodeAtCaret('data:' + contentType + ';base64,' + encoded);
  });
}

const codeElementWrapper = {
  get value() {
    return sourceEditor.getText();
  },

  set value(v) {
    sourceEditor.setText(v);
  },

  setSelectionRange: function (start, end) {
    sourceEditor.setSelection(sourceEditor.getPosition(start), sourceEditor.getPosition(end));
  },

  get selectionStart() {
    return sourceEditor.getOffset(sourceEditor.getCursor('start'));
  },

  get selectionEnd() {
    return sourceEditor.getOffset(sourceEditor.getCursor('end'));
  },
}

const closeFn = window.close;
let shouldHandle = true;

function closeWithoutAsking () {
  shouldHandle = false;
  closeFn();
}

function confirmClose () {
  if (confirm('Do you want to close and lose unsaved changes?')) {
    shouldHandle = false;
    setTimeout(closeFn);
  }
}

if (isChromeWindow) {
  window.close = function () {
    if (!unsaved)
      return closeWithoutAsking();

    if (style) {
      readFile(style.url, function () {
        const hasChanges = initialCode !== codeElementWrapper.value;
        hasChanges ? confirmClose() : closeWithoutAsking();
      });
    } else {
      codeElementWrapper.value ? confirmClose() : closeWithoutAsking();
    }
  }
}

window.addEventListener('close', function (e) {
  e.preventDefault();
  window.close();
})

window.addEventListener('beforeunload', function (e) {
  if (shouldHandle && unsaved)
    e.preventDefault();
});

window.addEventListener('unload', function (event) {
  if (style?.enabled && previewActive)
    style.register();

  if (previewActive) {
    _uc.sss.unregisterSheet(previewCode, previewOrigin);
    if (origin === _uc.sss.AGENT_SHEET || lastOrigin === _uc.sss.AGENT_SHEET)
      UC.styloaix.forceRefresh();
  }
});

window.addEventListener('DOMContentLoaded', init, {once: true});

@srjjgm
Copy link

srjjgm commented Feb 7, 2025

Thanks for trying to help. I used these modifications but it didn't work. The same problems I already reported continue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants