Instagram Index Page Better Layout. IG 首页的布局更好看
// ==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)
};
}
})();