Instagram - Better Layout

Instagram Index Page Better Layout. IG 首页的布局更好看

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Instagram - Better Layout
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Instagram Index Page Better Layout. IG 首页的布局更好看
// @author       Martin______X, Gemini AI
// @match        https://www.instagram.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=instagram.com
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    let $CREATED = false;
    let $WIDGET_INSTANCE = null;

    // --- Main Loop ---
    setInterval(process_interval, 1);

    function process_interval() {
        try {
            // --- 1. Strict URL Validation ---
            if (!is_homepage()) {
                hide_widget(true); // true = force close
                return;
            }

            const main_element = document.querySelector("main");
            if (!main_element) return;

            // --- 2. Homepage Layout Adjustment (80vw) ---
            adjust_central_layout(main_element);

            // --- 3. Enhanced Chat Window Visibility Detection ---
            const is_chat_visible = check_chat_visibility();

            // --- 4. Dynamic main_right Detection ---
            const main_right = get_main_right(main_element);

            // Core visibility logic: If no right sidebar, or chat window is visible, hide the button
            if (should_hide_widget(main_right, is_chat_visible)) {
                hide_widget(false); // false = just hide, don't force close state
                return;
            }

            // --- 5. Widget Creation and Refresh ---
            update_or_create_widget(main_element, main_right);

            // Story Tray Scaling Logic
            adjust_story_tray(main_element);

        } catch (e) {}
    }

    // --- Helper Functions ---

    function is_homepage() {
        return window.location.pathname === '/' || window.location.pathname === '';
    }

    function hide_widget(force_close) {
        if ($WIDGET_INSTANCE) {
            $WIDGET_INSTANCE.element.style.setProperty('display', 'none', 'important');
            if (force_close) {
                $WIDGET_INSTANCE.close();
            }
        }
    }

    function adjust_central_layout(main_element) {
        const central_container = get_central_container(main_element);
        if (central_container && central_container.style.maxWidth !== '80vw') {
            central_container.style.setProperty('max-width', '80vw', 'important');
            central_container.style.setProperty('width', '100%', 'important');
        }
    }

    function get_central_container(main_element) {
        if (!main_element || !main_element.firstElementChild) return null;
        return main_element.firstElementChild.firstElementChild;
    }

    function check_chat_visibility() {
        const chat_list = document.querySelector('[data-pagelet="IGDChatTabThreadList"]');
        if (chat_list) {
            const style = window.getComputedStyle(chat_list);
            // Simultaneously detect multiple hiding methods: offsetParent, CSS display, CSS visibility
            return (chat_list.offsetParent !== null) &&
                   (style.display !== 'none') &&
                   (style.visibility !== 'hidden');
        }
        return false;
    }

    function get_main_right(main_element) {
        if (!main_element || !main_element.firstElementChild) return null;
        return main_element.firstElementChild.children[1];
    }

    function should_hide_widget(main_right, is_chat_visible) {
        return !main_right || is_chat_visible;
    }

    function update_or_create_widget(main_element, main_right) {
        const current_bg_color = window.getComputedStyle(main_element).backgroundColor;

        if (!$CREATED) {
            main_right.style.margin = "0px";
            main_right.style.padding = "0px";
            $WIDGET_INSTANCE = create_floating_widget({
                content: main_right,
                btn_color: '#007AFF',
                max_height: '90vh',
                bg_color: current_bg_color
            });
            $CREATED = true;
        } else {
            // Meets display conditions, show and refresh content
            $WIDGET_INSTANCE.element.style.display = 'flex';
            if (main_right.style.display !== 'none') {
                main_right.style.marginLeft = "0px";
                main_right.style.paddingLeft = "0px";
                $WIDGET_INSTANCE.refresh_content(main_right);
            }
            $WIDGET_INSTANCE.update_bg(current_bg_color);
        }
    }

    function adjust_story_tray(main_element) {
        const central_container = get_central_container(main_element);
        if (!central_container) return;

        var target = central_container.querySelector('[data-pagelet="story_tray"] div > div > div > [role="presentation"]');
        if (target) {
            let sibling = target.nextElementSibling;
            while (sibling) {
                const btn = sibling.tagName === 'BUTTON' ? sibling : sibling.querySelector('button');
                if (btn) btn.style.setProperty('transform', 'scale(1.5) translateY(-15px)', 'important');
                sibling = sibling.nextElementSibling;
            }
            target.style.cssText = "max-width: 80% !important; margin-left: 10% !important; margin-right: 10% !important; width: 100% !important;";
        }
    }

    // --- create_floating_widget Internal Logic Splitting ---

    function get_dynamic_shadow(rgb_str) {
        const rgb = rgb_str.match(/\d+/g);
        if (!rgb || rgb.length < 3) return '0 10px 40px rgba(0,0,0,0.5)';
        const brightness = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;
        return brightness < 128 ? '0 0 25px 5px rgba(255, 255, 255, 0.12), 0 20px 50px rgba(0, 0, 0, 0.9)' : '0 15px 40px 5px rgba(0, 0, 0, 0.25), 0 5px 15px rgba(0, 0, 0, 0.1)';
    }

    function ensure_widget_styles(btn_color, max_height) {
        if (!document.getElementById('fw-style-tag')) {
            const style_tag = document.createElement('style');
            style_tag.id = 'fw-style-tag';
            style_tag.innerHTML = `
                .fw-wrapper {
                    position: fixed; right: 0; top: 50%;
                    transform: translateY(-50%);
                    display: flex; flex-direction: row-reverse;
                    align-items: center; z-index: 2147483647 !important;
                    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto;
                    pointer-events: none; padding: 0 10px 0 40px;
                }
                .fw-panel {
                    width: 350px; height: auto; max-height: ${max_height};
                    border-radius: 12px; opacity: 0; visibility: hidden;
                    transition: opacity 0.5s ease, visibility 0.5s ease, background-color 0.3s;
                    display: flex; flex-direction: column;
                    pointer-events: none; overflow-y: auto; scrollbar-width: none;
                    box-sizing: border-box; overscroll-behavior: contain !important;
                }
                .fw-panel::-webkit-scrollbar { display: none !important; }
                .fw-wrapper.is_open .fw-panel { opacity: 1; visibility: visible; pointer-events: auto; }
                .fw-content_inner { width: 100%; padding: 15px; box-sizing: border-box; }

                .fw-btn {
                    width: 50px !important; height: 50px !important;
                    background-color: ${btn_color} !important;
                    color: white !important; border: none !important;
                    border-radius: 50% !important; cursor: pointer !important;
                    display: grid !important; place-items: center !important;
                    transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), box-shadow 0.3s ease !important;
                    z-index: 2147483647 !important; margin-left: 15px !important;
                    pointer-events: auto !important; flex-shrink: 0;
                    position: relative; top: -12vh;
                }
                .fw-btn:hover { transform: scale(1.1) !important; }

                .fw-icon-stack { position: relative; width: 100%; height: 100%; display: grid; place-items: center; }
                .fw-icon { grid-area: 1/1; font-size: 28px; transition: all 0.4s ease; line-height: 1; }
                .fw-icon.filled { opacity: 1; transform: scale(1) rotate(0deg); }
                .fw-icon.outline { opacity: 0; transform: scale(0.5) rotate(-45deg); }
                .fw-wrapper.is_open .fw-icon.filled { opacity: 0; transform: scale(0.5) rotate(45deg); }
                .fw-wrapper.is_open .fw-icon.outline { opacity: 1; transform: scale(1) rotate(0deg); }
            `;
            document.head.appendChild(style_tag);
        }
    }

    function create_widget_dom() {
        const wrapper_div = document.createElement('div');
        wrapper_div.className = 'fw-wrapper';
        const panel_div = document.createElement('div');
        panel_div.className = 'fw-panel';
        const content_inner_div = document.createElement('div');
        content_inner_div.className = 'fw-content_inner';
        const main_btn = document.createElement('button');
        main_btn.className = 'fw-btn';

        main_btn.innerHTML = `<div class="fw-icon-stack"><span class="fw-icon filled">✦</span><span class="fw-icon outline">✧</span></div>`;

        return { wrapper_div, panel_div, content_inner_div, main_btn };
    }

    function apply_widget_theme(panel_div, main_btn, color_val) {
        panel_div.style.backgroundColor = color_val;
        const shadow_val = get_dynamic_shadow(color_val);
        panel_div.style.setProperty('box-shadow', shadow_val, 'important');
        main_btn.style.setProperty('box-shadow', shadow_val, 'important');
    }

    function inject_widget_content(content_inner_div, target_el) {
        content_inner_div.innerHTML = '';
        if (target_el instanceof HTMLElement) {
            target_el.style.display = 'none';
            const clone_node = target_el.cloneNode(true);
            clone_node.style.display = 'block';
            content_inner_div.appendChild(clone_node);
        }
    }

    function toggle_widget_state(wrapper_div, panel_div, force_close) {
        const is_currently_open = wrapper_div.classList.contains('is_open');
        const should_be_open = force_close ? false : !is_currently_open;
        if (should_be_open) {
            wrapper_div.classList.add('is_open');
            panel_div.scrollTo(0, 0);
        } else {
            wrapper_div.classList.remove('is_open');
        }
    }

    function setup_widget_events(main_btn, wrapper_div, toggle_fn) {
        main_btn.onclick = (e) => {
            e.stopPropagation();
            toggle_fn();
        };
        document.onclick = (e) => {
            if (!wrapper_div.contains(e.target) && wrapper_div.classList.contains('is_open')) toggle_fn(true);
        };
    }

    function create_floating_widget(options = {}) {
        const {
            content = '', btn_color = '#2563eb', max_height = '80vh', bg_color = 'rgb(255, 255, 255)'
        } = options;

        ensure_widget_styles(btn_color, max_height);

        const { wrapper_div, panel_div, content_inner_div, main_btn } = create_widget_dom();

        const toggle = (force_close) => toggle_widget_state(wrapper_div, panel_div, force_close);
        const update_bg = (new_c) => apply_widget_theme(panel_div, main_btn, new_c);
        const refresh_content = (new_t) => inject_widget_content(content_inner_div, new_t);

        // Initialization
        refresh_content(content);
        panel_div.appendChild(content_inner_div);
        wrapper_div.append(main_btn, panel_div);
        document.body.appendChild(wrapper_div);
        update_bg(bg_color);

        setup_widget_events(main_btn, wrapper_div, toggle);

        $CREATED = true;
        return {
            element: wrapper_div,
            update_bg: update_bg,
            refresh_content: refresh_content,
            close: () => toggle(true)
        };
    }
})();