Commit 0cd0e345 authored by Stefy Spora's avatar Stefy Spora

Add privacy level dropdown menu for flexible privacy settings

- Add dropdown menu to select between 'Friends Only' and 'All Fetlifers' privacy levels
- Update XHR payloads to use selected privacy level for both pictures and videos
- Pictures: 'only_friends' vs 'public' based on selection
- Videos: true vs false for only_friends based on selection
- Update popup.js to pass privacy level to content script functions
- Update background.js context menu functions to use privacy level
- Update content.js executePrivacyUpdate function to accept privacy level parameter
- Update README.md with privacy level selection instructions
- Add version 1.0.3 to CHANGELOG.md documenting the new feature
- Maintain backward compatibility with default 'friends_only' setting
parent 25b6b4cb
......@@ -5,6 +5,19 @@ All notable changes to the FetLife Privacy Helper extension will be documented i
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.3] - 2025-08-31
### Added
- **Privacy Level Selection**: Added dropdown menu to choose between "Friends Only" and "All Fetlifers" privacy settings
- **Dynamic Privacy Settings**: Extension now respects user-selected privacy level for both pictures and videos
- **Flexible Privacy Control**: Users can set media to friends-only or make it visible to all FetLife users
### Enhanced
- **User Interface**: Added privacy level selector above the action buttons
- **Privacy Options**: Pictures can be set to "only_friends" or "public"
- **Video Privacy**: Videos can be set to friends-only (true) or all users (false)
- **Bulk Processing**: Privacy level selection applies to all bulk operations
## [1.0.2] - 2025-08-31
### Added
......
......@@ -10,10 +10,11 @@ A Chrome browser extension that automates privacy settings on FetLife.com. When
## Features
- **Privacy Level Selection**: Choose between "Friends Only" or "All Fetlifers" privacy settings
- **Single Update**: Click the "Privaxy" button in the extension popup
- **Bulk Processing**: Click "Run on All Media" to process multiple pages automatically
- **Context Menu**: Right-click on any FetLife page and select "Privaxy" or "Run on All Media"
- **Automatic Privacy Update**: Finds the Edit button, changes privacy to "only friends", and saves changes
- **Automatic Privacy Update**: Uses XHR requests to update privacy settings directly
- **Pagination Support**: Automatically follows "next »" links to process multiple pages
- **Stop Control**: Stop bulk processing at any time with the Stop button
- **Progress Tracking**: Shows real-time progress during bulk operations
......@@ -32,16 +33,18 @@ A Chrome browser extension that automates privacy settings on FetLife.com. When
### Method 1: Single Page Update (Extension Popup)
1. Navigate to a FetLife picture or video page
2. Click the extension icon in your Chrome toolbar
3. Click the "Privaxy" button in the popup
4. Wait for the success message
3. Select your desired privacy level from the dropdown ("Friends Only" or "All Fetlifers")
4. Click the "Privaxy" button in the popup
5. Wait for the success message
### Method 2: Bulk Processing (Extension Popup)
1. Navigate to a FetLife gallery or list page with multiple media items
2. Click the extension icon in your Chrome toolbar
3. Click the "Run on All Media" button in the popup
4. Watch the progress counter as it processes each page
5. Click "Stop" at any time to halt the process
6. Wait for the completion summary
3. Select your desired privacy level from the dropdown ("Friends Only" or "All Fetlifers")
4. Click the "Run on All Media" button in the popup
5. Watch the progress counter as it processes each page
6. Click "Stop" at any time to halt the process
7. Wait for the completion summary
### Method 3: Context Menu (Single Page)
1. Navigate to a FetLife picture or video page
......
......@@ -42,10 +42,11 @@ chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.onClicked.addListener(async (info, tab) => {
if (info.menuItemId === 'privaxy') {
try {
// Execute the privacy update function
// Execute the privacy update function with default privacy level
const results = await chrome.scripting.executeScript({
target: { tabId: tab.id },
function: executePrivacyUpdateFromContext
function: (privacyLevel) => executePrivacyUpdateFromContext(privacyLevel),
args: ['friends_only']
});
const result = results[0].result;
......@@ -96,7 +97,7 @@ chrome.contextMenus.onClicked.addListener(async (info, tab) => {
});
// Function to be injected for context menu execution - XHR-based approach
function executePrivacyUpdateFromContext() {
function executePrivacyUpdateFromContext(privacyLevel = 'friends_only') {
// Function to extract media ID and type from URL
function getMediaInfo() {
const url = window.location.href;
......@@ -150,14 +151,14 @@ function executePrivacyUpdateFromContext() {
throw new Error('Could not find CSRF token. Please refresh the page and try again.');
}
// Step 3: Prepare payload based on media type
// Step 3: Prepare payload based on media type and privacy level
let payload;
if (mediaInfo.type === 'video') {
payload = {
video: {
title: "",
description: "",
only_friends: true,
only_friends: privacyLevel === 'friends_only' ? true : false,
tag_names: [],
user_tag_ids: []
},
......@@ -167,7 +168,7 @@ function executePrivacyUpdateFromContext() {
payload = {
picture: {
caption: "",
content_privacy: "only_friends",
content_privacy: privacyLevel === 'friends_only' ? "only_friends" : "public",
tag_names: [],
user_tag_ids: []
},
......@@ -252,7 +253,7 @@ function executeBulkPrivacyUpdateFromContext() {
return mediaIds;
}
async function updateMediaPrivacyById(mediaType, mediaId, csrfToken) {
async function updateMediaPrivacyById(mediaType, mediaId, csrfToken, privacyLevel = 'friends_only') {
try {
let payload;
if (mediaType === 'video') {
......@@ -260,7 +261,7 @@ function executeBulkPrivacyUpdateFromContext() {
video: {
title: "",
description: "",
only_friends: true,
only_friends: privacyLevel === 'friends_only' ? true : false,
tag_names: [],
user_tag_ids: []
},
......@@ -270,7 +271,7 @@ function executeBulkPrivacyUpdateFromContext() {
payload = {
picture: {
caption: "",
content_privacy: "only_friends",
content_privacy: privacyLevel === 'friends_only' ? "only_friends" : "public",
tag_names: [],
user_tag_ids: []
},
......@@ -354,7 +355,7 @@ function executeBulkPrivacyUpdateFromContext() {
// Process all media items on current page
for (const item of mediaItems) {
try {
const result = await updateMediaPrivacyById(item.type, item.id, csrfToken);
const result = await updateMediaPrivacyById(item.type, item.id, csrfToken, 'friends_only');
if (result.success) {
successCount++;
} else {
......
......@@ -96,9 +96,9 @@
}
// Main function to execute privacy update via XHR
async function executePrivacyUpdate() {
async function executePrivacyUpdate(privacyLevel = 'friends_only') {
try {
console.log('Starting XHR-based privacy update...');
console.log('Starting XHR-based privacy update with privacy level:', privacyLevel);
// Step 1: Detect media type and ID from URL
const mediaInfo = getMediaInfo();
......@@ -117,14 +117,14 @@
// Step 3: Get current media data to preserve existing values
const currentData = await getCurrentMediaData(mediaInfo.type, mediaInfo.id);
// Step 4: Prepare payload based on media type
// Step 4: Prepare payload based on media type and privacy level
let payload;
if (mediaInfo.type === 'video') {
payload = {
video: {
title: currentData.title,
description: currentData.description,
only_friends: true,
only_friends: privacyLevel === 'friends_only' ? true : false,
tag_names: currentData.tag_names,
user_tag_ids: currentData.user_tag_ids
},
......@@ -134,7 +134,7 @@
payload = {
picture: {
caption: currentData.caption,
content_privacy: "only_friends",
content_privacy: privacyLevel === 'friends_only' ? "only_friends" : "public",
tag_names: currentData.tag_names,
user_tag_ids: currentData.user_tag_ids
},
......
......@@ -84,6 +84,15 @@
</head>
<body>
<div class="header">FetLife Privacy Helper</div>
<div style="margin-bottom: 10px; text-align: center;">
<label for="privacy-select" style="font-size: 12px; color: #666; margin-right: 5px;">Privacy Level:</label>
<select id="privacy-select" style="padding: 3px 6px; border: 1px solid #ccc; border-radius: 3px; font-size: 12px; background-color: white;">
<option value="friends_only">👥 Friends Only</option>
<option value="all_fetlifers">🌐 All Fetlifers</option>
</select>
</div>
<button id="privaxy-btn" class="privaxy-btn">Privaxy</button>
<button id="run-all-btn" class="privaxy-btn" style="background-color: #2196F3; margin-top: 5px;">Run on All Media</button>
<button id="stop-btn" class="privaxy-btn" style="background-color: #f44336; margin-top: 5px; display: none;">Stop</button>
......
......@@ -134,12 +134,17 @@ document.addEventListener('DOMContentLoaded', function() {
return;
}
// Get selected privacy level
const privacySelect = document.getElementById('privacy-select');
const privacyLevel = privacySelect.value;
showStatus('Executing privacy update...', 'info');
// Execute the content script function
// Execute the content script function with privacy level
const results = await chrome.scripting.executeScript({
target: { tabId: tab.id },
function: executePrivacyUpdate
function: (privacyLevel) => executePrivacyUpdate(privacyLevel),
args: [privacyLevel]
});
const result = results[0].result;
......@@ -186,10 +191,15 @@ document.addEventListener('DOMContentLoaded', function() {
showProgress(`Processing page ${pageCount}... (${successCount} success, ${errorCount} errors)`);
try {
// Execute privacy update on current page
// Get selected privacy level
const privacySelect = document.getElementById('privacy-select');
const privacyLevel = privacySelect.value;
// Execute privacy update on current page with privacy level
const results = await chrome.scripting.executeScript({
target: { tabId: tab.id },
function: executePrivacyUpdate
function: (privacyLevel) => executePrivacyUpdate(privacyLevel),
args: [privacyLevel]
});
const result = results[0].result;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment