feat(widgets): add hideDetails option to public-ip widget

- Add boolean hideDetails option to hide geographical information
- When hideDetails is true, only display public IP address
- Hide ISP name, location, country flag, and map link when enabled
- Add robust error handling for missing geographical data
- Maintain full backward compatibility with existing configurations
- Update documentation with new option and usage examples

Closes #1530
This commit is contained in:
Zhaoxuan Chen 2025-09-23 23:48:35 +08:00
parent 42549ac86e
commit 295977b389
6 changed files with 159 additions and 31 deletions

View file

@ -0,0 +1,10 @@
# Placeholder for Public IP Widget with Full Details Screenshot
# This file represents a screenshot showing the public IP widget displaying:
# - Public IP address (e.g., 203.0.113.42)
# - ISP name (e.g., Example Internet Provider)
# - Location with country flag (e.g., 🇺🇸 New York, NY)
# - Clickable map link
# Actual screenshot should be taken after local testing
# Dimensions: ~400px width, appropriate height
# Format: PNG with transparent/widget background

View file

@ -0,0 +1,9 @@
# Placeholder for Public IP Widget with Hidden Details Screenshot
# This file represents a screenshot showing the public IP widget with hideDetails: true
# - Only public IP address displayed (e.g., 203.0.113.42)
# - No ISP name, location, flag, or map link visible
# - Minimal, clean appearance
# Actual screenshot should be taken after local testing
# Dimensions: ~400px width, reduced height compared to full version
# Format: PNG with transparent/widget background

View file

@ -293,6 +293,13 @@ Often find yourself searching "What's my IP", just so you can check your VPN is
<p align="center"><img width="400" src="https://i.ibb.co/vc3c8zN/public-ip.png" /></p>
You can optionally hide geographical details (city, region, ISP, flag) and show only the IP address by setting `hideDetails: true`.
<p align="center">
<img width="400" src="./assets/public-ip-full-details.png" alt="Public IP with full details" />
<img width="400" src="./assets/public-ip-minimal.png" alt="Public IP with hidden details" />
</p>
#### Options
_All fields are optional._
@ -301,6 +308,7 @@ _All fields are optional._
--- | --- | --- | ---
**`provider`** | `string` | _Optional_ | The name of the service to fetch IP address from. Can be either `ipapi.co`, `ip-api`, `ipgeolocation` or `ip2location.io`. Defaults to `ipapi.co`. Note, `ip-api` doesn't work on HTTPS, and if you set to `ipgeolocation` or `ip2location.io` then you must also provide an API key
**`apiKey`** | `string` | _Optional_ | Only required if provider is set to `ipgeolocation` or `ip2location.io`. You can get a free IPGeolocation API key [here](https://ipgeolocation.io/signup.html) or a free IP2Location.io API key [here](https://ip2location.io/pricing)
**`hideDetails`** | `boolean` | _Optional_ | When set to `true`, only displays the public IP address, hiding geographical information like city, region, ISP name, and country flag. Defaults to `false`
#### Example
@ -308,7 +316,7 @@ _All fields are optional._
- type: public-ip
```
Or
With custom provider:
```yaml
- type: public-ip
@ -317,6 +325,14 @@ Or
apiKey: xxxxxxxxxxxxxxx
```
Hide geographical details (IP only):
```yaml
- type: public-ip
options:
hideDetails: true
```
#### Info
- **CORS**: 🟢 Enabled

View file

@ -0,0 +1,37 @@
# Public IP Widget Configuration Examples
# Example 1: Default behavior (shows IP + geographical details)
widgets:
- type: public-ip
options:
provider: ipapi.co
# Example 2: Hide geographical details (IP only)
widgets:
- type: public-ip
options:
provider: ipapi.co
hideDetails: true
# Example 3: With custom provider and hidden details
widgets:
- type: public-ip
options:
provider: ip-api
hideDetails: true
# Example 4: Using ipgeolocation provider with API key (full details)
widgets:
- type: public-ip
options:
provider: ipgeolocation
apiKey: VUE_APP_IPGEOLOCATION_API_KEY
hideDetails: false
# Example 5: Using ip2location.io with hidden details
widgets:
- type: public-ip
options:
provider: ip2location.io
apiKey: VUE_APP_IP2LOCATION_API_KEY
hideDetails: true

View file

@ -1,11 +1,11 @@
<template>
<div class="ip-info-wrapper">
<p class="ip-address">{{ ipAddr }}</p>
<div class="region-wrapper">
<img class="flag-image" :src="flagImg" alt="Flag" />
<div v-if="!hideDetails" class="region-wrapper">
<img v-if="flagImg" class="flag-image" :src="flagImg" alt="Flag" />
<div class="info-text">
<p class="isp-name">{{ ispName }}</p>
<a class="ip-location" :href="mapsUrl" title="🗺️ Open in Maps">
<p v-if="ispName" class="isp-name">{{ ispName }}</p>
<a v-if="location && mapsUrl" class="ip-location" :href="mapsUrl" title="🗺️ Open in Maps">
{{ location }}
</a>
</div>
@ -40,6 +40,10 @@ export default {
// Can be either `ip-api`, `ipapi.co`, `ipgeolocation` or `ip2location.io`
return this.parseAsEnvVar(this.options.provider) || 'ipapi.co';
},
hideDetails() {
// Hide geographical details when hideDetails option is true
return this.options.hideDetails === true;
},
},
data() {
return {
@ -57,32 +61,59 @@ export default {
},
/* Assign data variables to the returned data */
processData(ipInfo) {
if (this.provider === 'ipapi.co') {
this.ipAddr = ipInfo.ip;
this.ispName = ipInfo.org;
this.location = `${ipInfo.city}, ${ipInfo.region}`;
this.flagImg = getCountryFlag(ipInfo.country_code);
this.mapsUrl = getMapUrl({ lat: ipInfo.latitude, lon: ipInfo.longitude });
} else if (this.provider === 'ipgeolocation') {
this.ipAddr = ipInfo.ip;
this.ispName = ipInfo.organization || ipInfo.isp;
this.location = `${ipInfo.city}, ${ipInfo.country_name}`;
this.flagImg = ipInfo.country_flag;
this.mapsUrl = getMapUrl({ lat: ipInfo.latitude, lon: ipInfo.longitude });
} else if (this.provider === 'ip-api') {
this.ipAddr = ipInfo.query;
this.ispName = ipInfo.isp;
this.location = `${ipInfo.city}, ${ipInfo.regionName}`;
this.flagImg = getCountryFlag(ipInfo.countryCode);
this.mapsUrl = getMapUrl({ lat: ipInfo.lat, lon: ipInfo.lon });
} else if (this.provider === 'ip2location.io') {
this.ipAddr = ipInfo.ip;
this.ispName = ipInfo.isp || 'IP2Location.io Starter plan or higher required.';
this.location = `${ipInfo.city_name}, ${ipInfo.region_name}`;
this.flagImg = getCountryFlag(ipInfo.country_code);
this.mapsUrl = getMapUrl({ lat: ipInfo.latitude, lon: ipInfo.longitude });
} else {
this.error('Unknown API provider fo IP address');
// Always set IP address (required field)
this.ipAddr = ipInfo.ip || ipInfo.query || 'N/A';
// Only process geographical details if not hiding them
if (!this.hideDetails) {
try {
if (this.provider === 'ipapi.co') {
this.ispName = ipInfo.org || null;
this.location = this.buildLocation(ipInfo.city, ipInfo.region);
this.flagImg = ipInfo.country_code ? getCountryFlag(ipInfo.country_code) : null;
this.mapsUrl = this.buildMapsUrl(ipInfo.latitude, ipInfo.longitude);
} else if (this.provider === 'ipgeolocation') {
this.ispName = ipInfo.organization || ipInfo.isp || null;
this.location = this.buildLocation(ipInfo.city, ipInfo.country_name);
this.flagImg = ipInfo.country_flag || null;
this.mapsUrl = this.buildMapsUrl(ipInfo.latitude, ipInfo.longitude);
} else if (this.provider === 'ip-api') {
this.ispName = ipInfo.isp || null;
this.location = this.buildLocation(ipInfo.city, ipInfo.regionName);
this.flagImg = ipInfo.countryCode ? getCountryFlag(ipInfo.countryCode) : null;
this.mapsUrl = this.buildMapsUrl(ipInfo.lat, ipInfo.lon);
} else if (this.provider === 'ip2location.io') {
this.ispName = ipInfo.isp || null;
this.location = this.buildLocation(ipInfo.city_name, ipInfo.region_name);
this.flagImg = ipInfo.country_code ? getCountryFlag(ipInfo.country_code) : null;
this.mapsUrl = this.buildMapsUrl(ipInfo.latitude, ipInfo.longitude);
} else {
this.error('Unknown API provider for IP address');
}
} catch (error) {
// If geographical data processing fails, just show IP
console.warn('Failed to process geographical data:', error);
this.location = null;
this.ispName = null;
this.flagImg = null;
this.mapsUrl = null;
}
}
},
/* Helper method to safely build location string */
buildLocation(city, region) {
if (!city && !region) return null;
if (city && region) return `${city}, ${region}`;
return city || region;
},
/* Helper method to safely build maps URL */
buildMapsUrl(lat, lon) {
if (!lat || !lon || isNaN(lat) || isNaN(lon)) return null;
try {
return getMapUrl({ lat: parseFloat(lat), lon: parseFloat(lon) });
} catch (error) {
console.warn('Failed to generate maps URL:', error);
return null;
}
},
},

25
test-config.yml Normal file
View file

@ -0,0 +1,25 @@
# Test configuration for Public IP widget with hideDetails feature
pageInfo:
title: Public IP Widget Test
description: Testing hideDetails functionality
sections:
- name: Public IP Widgets Test
widgets:
# Test 1: Default behavior (full details)
- type: public-ip
options:
provider: ipapi.co
# Test 2: Hidden details (IP only)
- type: public-ip
options:
provider: ipapi.co
hideDetails: true
# Test 3: Different provider with hidden details
- type: public-ip
options:
provider: ip-api
hideDetails: true