Instagram - Better Layout

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

Du musst eine Erweiterung wie Tampermonkey, Greasemonkey oder Violentmonkey installieren, um dieses Skript zu installieren.

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

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

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

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

Sie müssten eine Skript Manager Erweiterung installieren damit sie dieses Skript installieren können

(Ich habe schon ein Skript Manager, Lass mich es installieren!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==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)
        };
    }
})();