Compare commits
27
Commits
ca3aaaf163
...
bl.v1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60feffc256 | ||
|
|
07504555b6 | ||
|
|
320b4b2825 | ||
|
|
97c1e48e91 | ||
|
|
308d63b8d8 | ||
|
|
6808e88599 | ||
|
|
f16efce66e | ||
|
|
0f01b836c6 | ||
|
|
be517f56a5 | ||
|
|
655b01be50 | ||
|
|
5d98f474ae | ||
|
|
15baafc9be | ||
|
|
00703e013c | ||
|
|
57861a19c6 | ||
|
|
feb32c9cd1 | ||
|
|
340a32c301 | ||
|
|
f711e5ee36 | ||
|
|
48b40136cf | ||
|
|
564877e1e7 | ||
|
|
8d3d571954 | ||
|
|
a48cc91680 | ||
|
|
a5f5d415e2 | ||
|
|
a2c74dc52f | ||
|
|
2ced76049b | ||
|
|
dc63fffb67 | ||
|
|
d5150ba126 | ||
|
|
b8401b3613 |
@@ -1 +1,4 @@
|
|||||||
/build
|
/build
|
||||||
|
.gradle
|
||||||
|
/app/build
|
||||||
|
local.properties
|
||||||
|
|||||||
@@ -0,0 +1,450 @@
|
|||||||
|
# BlueToothLogger Android Application - Technical Project Context
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
**Project Name:** BlueToothLogger
|
||||||
|
**Package:** `com.wytehat.btlogger`
|
||||||
|
**Location:** `/Users/n0tst3v3/bletracker/BlueToothLogger`
|
||||||
|
**Type:** Bluetooth tracking and logging application with spatial analysis capabilities
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Classes and Inheritance
|
||||||
|
|
||||||
|
| Class | Extends | Implements | Purpose |
|
||||||
|
|-------|---------|------------|---------|
|
||||||
|
| `MainActivity` | Activity | ItemActionListener | Main entry point, UI controller |
|
||||||
|
| `BluetoothTrackingService` | Service | LocationListener | Background Bluetooth tracking |
|
||||||
|
| `TrackerDatabase` | SQLiteOpenHelper | - | SQLite database wrapper |
|
||||||
|
| `MapActivity` | Activity | - | Map visualization |
|
||||||
|
| `DeviceManagerActivity` | Activity | - | Device management UI |
|
||||||
|
| `LiveRangeFinderActivity` | Activity | LocationListener, SensorEventListener | Real-time signal finder |
|
||||||
|
| `BluetoothRadarView` | View | - | Custom radar visualization |
|
||||||
|
| `DeviceListAdapter` | BaseAdapter | - | List adapter for devices |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## BluetoothTrackingService - Technical Details
|
||||||
|
|
||||||
|
### Constants
|
||||||
|
```java
|
||||||
|
public static final String ACTION_DATA_CHANGED = "com.wytehat.btlogger.DATA_CHANGED"
|
||||||
|
public static final String ACTION_CONFIG_CHANGED = "com.wytehat.btlogger.CONFIG_CHANGED"
|
||||||
|
public static final String ACTION_RANGE_MODE = "com.wytehat.btlogger.RANGE_MODE"
|
||||||
|
private static final int NOTIFICATION_ID = 42
|
||||||
|
private static final String CHANNEL_ID = "bluetooth_tracking"
|
||||||
|
private static final String ALERT_CHANNEL_ID = "tracked_item_disconnects"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
```java
|
||||||
|
private TrackerDatabase db
|
||||||
|
private LocationManager locationManager
|
||||||
|
private BluetoothAdapter bluetooth
|
||||||
|
private Location lastLocation
|
||||||
|
private boolean receiverRegistered
|
||||||
|
private boolean rangeModeActive
|
||||||
|
private int phoneBattery = 100
|
||||||
|
private final Handler handler = new Handler()
|
||||||
|
private final HashMap<String, Long> lastPeriodicLog
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Methods
|
||||||
|
```java
|
||||||
|
public void onCreate()
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId)
|
||||||
|
public void onDestroy()
|
||||||
|
public IBinder onBind(Intent intent)
|
||||||
|
|
||||||
|
// Location callbacks
|
||||||
|
public void onLocationChanged(Location location)
|
||||||
|
public void onProviderDisabled(String provider)
|
||||||
|
public void onProviderEnabled(String provider)
|
||||||
|
public void onStatusChanged(String provider, int status, Bundle extras)
|
||||||
|
|
||||||
|
// Bluetooth callbacks
|
||||||
|
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
|
||||||
|
|
||||||
|
// Private methods
|
||||||
|
private void loadLastLocation()
|
||||||
|
private void configureLocation()
|
||||||
|
private int shortestActiveInterval()
|
||||||
|
private void stopLocation()
|
||||||
|
private void captureFresh(String address, long eventTime)
|
||||||
|
private TrackerDatabase.Fix currentFix()
|
||||||
|
private TrackerDatabase.Fix fix(Location location)
|
||||||
|
private void resolveVendor(String address, int companyId)
|
||||||
|
private String bytesToHex(byte[] data)
|
||||||
|
private int parseCompanyId(byte[] scanRecord)
|
||||||
|
private String infer(DeviceRecord record)
|
||||||
|
private void disconnectAll(String reason)
|
||||||
|
private void syncPairedDevices()
|
||||||
|
private void restartBackgroundScan()
|
||||||
|
private boolean shouldBackgroundScan()
|
||||||
|
private boolean isLocationEligible(DeviceRecord record, long now)
|
||||||
|
private void notifyChanged()
|
||||||
|
private boolean hasLocationPermission()
|
||||||
|
private boolean hasBluetoothPermission()
|
||||||
|
private String address(BluetoothDevice device)
|
||||||
|
private String name(BluetoothDevice device)
|
||||||
|
private Location newer(Location first, Location second)
|
||||||
|
private void showDisconnectAlert(DeviceRecord record, String reason)
|
||||||
|
private Notification buildNotification()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## TrackerDatabase - Technical Details
|
||||||
|
|
||||||
|
### Constants
|
||||||
|
```java
|
||||||
|
private static final String DB_NAME = "bluetooth_tracker.db"
|
||||||
|
private static final int DB_VERSION = 15
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inner Class: Fix
|
||||||
|
```java
|
||||||
|
public static class Fix {
|
||||||
|
public double latitude
|
||||||
|
public double longitude
|
||||||
|
public float accuracy
|
||||||
|
public Fix(double lat, double lon, float acc)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Methods
|
||||||
|
```java
|
||||||
|
public TrackerDatabase(Context context)
|
||||||
|
public void onCreate(SQLiteDatabase db)
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
|
||||||
|
|
||||||
|
// Device tracking
|
||||||
|
public synchronized void connected(String address, String broadcast, long time, Fix fix)
|
||||||
|
public synchronized void disconnected(String address, String broadcast, long time, String reason)
|
||||||
|
public synchronized void telemetry(String address, String broadcast, Integer battery, String vendor, String category, long time)
|
||||||
|
public synchronized void recordObservation(String address, long time, int rssi, int txPower)
|
||||||
|
public synchronized void updateLocation(String address, Fix fix, long time)
|
||||||
|
|
||||||
|
// Profile and calibration
|
||||||
|
public synchronized void updateProfile(String address, String title, String photo, String color, long time)
|
||||||
|
public synchronized void updateCalibration(String address, int txPower, double exponent)
|
||||||
|
|
||||||
|
// Range finding
|
||||||
|
public synchronized void logRangeSample(String address, String sessionId, long time, int rssi, double distance)
|
||||||
|
|
||||||
|
// Tracking settings
|
||||||
|
public synchronized void updateTracking(String address, int minutes, String color)
|
||||||
|
public synchronized void markTracked(String address, String broadcast)
|
||||||
|
public synchronized void removeFromTracking(String address)
|
||||||
|
public synchronized void setMapEnabled(String address, boolean enabled)
|
||||||
|
public synchronized void setLiveEnabled(String address, boolean enabled)
|
||||||
|
public synchronized void setTrackBroadcast(String address, boolean enabled)
|
||||||
|
public synchronized void setShowTrail(String address, boolean shown)
|
||||||
|
public synchronized void setLocationLocked(String address, boolean locked)
|
||||||
|
public synchronized void setCustomName(String address, String name)
|
||||||
|
public synchronized void setDetectedCategory(String address, String category)
|
||||||
|
public synchronized void setCategory(String address, String category)
|
||||||
|
public synchronized void setVendor(String address, String vendor)
|
||||||
|
public synchronized void setManualVendor(String address, String vendor)
|
||||||
|
|
||||||
|
// Lookups
|
||||||
|
public synchronized String lookupOui(String address)
|
||||||
|
public synchronized String lookupCompany(int companyId)
|
||||||
|
|
||||||
|
// Queries
|
||||||
|
public synchronized DeviceRecord get(String address)
|
||||||
|
public synchronized List<DeviceRecord> all()
|
||||||
|
public synchronized List<DeviceRecord> tracked()
|
||||||
|
public synchronized List<LocationPoint> history(String address, long since)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MainActivity - Technical Details
|
||||||
|
|
||||||
|
### Constants
|
||||||
|
```java
|
||||||
|
private static final int PERMISSIONS = 100
|
||||||
|
private static final int CAMERA = 200
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
```java
|
||||||
|
private TrackerDatabase db
|
||||||
|
private DeviceListAdapter adapter
|
||||||
|
private boolean registered
|
||||||
|
private DeviceRecord editing
|
||||||
|
private final Handler refreshHandler = new Handler()
|
||||||
|
private final Runnable refreshLiveAvailability
|
||||||
|
private final BroadcastReceiver updates
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Methods
|
||||||
|
```java
|
||||||
|
protected void onCreate(Bundle state)
|
||||||
|
protected void onResume()
|
||||||
|
protected void onPause()
|
||||||
|
protected void onDestroy()
|
||||||
|
|
||||||
|
// UI actions
|
||||||
|
public void edit(DeviceRecord record)
|
||||||
|
public void map(DeviceRecord record)
|
||||||
|
public void live(DeviceRecord record)
|
||||||
|
public void manage(DeviceRecord record)
|
||||||
|
|
||||||
|
// Device operations
|
||||||
|
private void removeTrackedItem(DeviceRecord record)
|
||||||
|
private void toggleBroadcastTracking(DeviceRecord record)
|
||||||
|
private void toggleTrail(DeviceRecord record)
|
||||||
|
private void refind(DeviceRecord record)
|
||||||
|
|
||||||
|
// Renaming and settings
|
||||||
|
private void rename(DeviceRecord record)
|
||||||
|
private void chooseTracking(DeviceRecord record)
|
||||||
|
private void chooseColor(DeviceRecord record, int minutes)
|
||||||
|
private void takePhoto()
|
||||||
|
protected void onActivityResult(int request, int result, Intent data)
|
||||||
|
private void showSettings()
|
||||||
|
private void openNotificationSettings()
|
||||||
|
private void openAppSettings(String instruction)
|
||||||
|
private boolean isBatteryOptimizationDisabled()
|
||||||
|
private void requestBackgroundProtection()
|
||||||
|
private void showTrackingInformation()
|
||||||
|
|
||||||
|
// Permissions
|
||||||
|
public void onRequestPermissionsResult(int request, String[] permissions, int[] results)
|
||||||
|
private void requestNeededPermissions()
|
||||||
|
private void addPermission(List<String> list, String permission)
|
||||||
|
private void reload()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## LiveRangeFinderActivity - Technical Details
|
||||||
|
|
||||||
|
### Implements
|
||||||
|
```java
|
||||||
|
implements LocationListener, SensorEventListener, ItemActionListener
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Methods
|
||||||
|
```java
|
||||||
|
protected void onCreate(Bundle savedState)
|
||||||
|
protected void onPause()
|
||||||
|
protected void onDestroy()
|
||||||
|
|
||||||
|
// Location callbacks
|
||||||
|
public void onLocationChanged(Location location)
|
||||||
|
public void onProviderDisabled(String provider)
|
||||||
|
public void onProviderEnabled(String provider)
|
||||||
|
public void onStatusChanged(String provider, int status, Bundle extras)
|
||||||
|
|
||||||
|
// Sensor callbacks
|
||||||
|
public void onSensorChanged(SensorEvent event)
|
||||||
|
public void onAccuracyChanged(Sensor sensor, int accuracy)
|
||||||
|
|
||||||
|
// Bluetooth callbacks
|
||||||
|
public void onScanResult(int callbackType, ScanResult result)
|
||||||
|
public void onBatchScanResults(List<ScanResult> results)
|
||||||
|
public void onScanFailed(int errorCode)
|
||||||
|
|
||||||
|
// UI actions
|
||||||
|
private void startSearch()
|
||||||
|
private void stopSearch(String message)
|
||||||
|
private void tagItemHere()
|
||||||
|
private void startCalibration()
|
||||||
|
private void updateRadar()
|
||||||
|
private void updateRangeDisplay()
|
||||||
|
private void updateDistanceDisplay()
|
||||||
|
private void updateCalibrationDisplay()
|
||||||
|
private void updateSearchDisplay()
|
||||||
|
private void updateSearchStatus()
|
||||||
|
private void updateSearchProgress()
|
||||||
|
private void updateSearchResults()
|
||||||
|
private void updateSearchSettings()
|
||||||
|
private void updateSearchControls()
|
||||||
|
private void updateSearchUI()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MapActivity - Technical Details
|
||||||
|
|
||||||
|
### Implements
|
||||||
|
```java
|
||||||
|
implements LocationListener, SensorEventListener, ItemActionListener
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Methods
|
||||||
|
```java
|
||||||
|
protected void onCreate(Bundle state)
|
||||||
|
protected void onResume()
|
||||||
|
protected void onPause()
|
||||||
|
protected void onDestroy()
|
||||||
|
|
||||||
|
// Location callbacks
|
||||||
|
public void onLocationChanged(Location location)
|
||||||
|
public void onProviderDisabled(String provider)
|
||||||
|
public void onProviderEnabled(String provider)
|
||||||
|
public void onStatusChanged(String provider, int status, Bundle extras)
|
||||||
|
|
||||||
|
// Sensor callbacks
|
||||||
|
public void onSensorChanged(SensorEvent event)
|
||||||
|
public void onAccuracyChanged(Sensor sensor, int accuracy)
|
||||||
|
|
||||||
|
// Map operations
|
||||||
|
private void updateMap()
|
||||||
|
private void updateMarkers()
|
||||||
|
private void updateTrails()
|
||||||
|
private void updateCamera()
|
||||||
|
private void updateLocation()
|
||||||
|
private void updateRange()
|
||||||
|
private void updateCalibration()
|
||||||
|
private void updateSearch()
|
||||||
|
private void updateSettings()
|
||||||
|
private void updateUI()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DeviceManagerActivity - Technical Details
|
||||||
|
|
||||||
|
### Key Methods
|
||||||
|
```java
|
||||||
|
protected void onCreate(Bundle state)
|
||||||
|
protected void onPause()
|
||||||
|
protected void onDestroy()
|
||||||
|
|
||||||
|
// Bluetooth scanning
|
||||||
|
private void startScan()
|
||||||
|
private void stopScan()
|
||||||
|
private void refreshCategoryOptions()
|
||||||
|
private void updateRadar()
|
||||||
|
|
||||||
|
// Device management
|
||||||
|
private void toggleMap(DeviceRecord record, Button button)
|
||||||
|
private void toggleTrack(DeviceRecord record, Button button)
|
||||||
|
private void editSignal(DeviceRecord record)
|
||||||
|
private void confirmRemoveSignal(SignalEntry entry)
|
||||||
|
private void copyText(String label, String text)
|
||||||
|
|
||||||
|
// Adapters
|
||||||
|
private class SignalGridAdapter extends BaseAdapter
|
||||||
|
private class PairedAdapter extends BaseAdapter
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## BluetoothRadarView - Technical Details
|
||||||
|
|
||||||
|
### Extends
|
||||||
|
```java
|
||||||
|
extends View
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Features
|
||||||
|
- Custom radar-like visualization
|
||||||
|
- Radial gradient rendering
|
||||||
|
- Touch event handling
|
||||||
|
- Signal strength visualization
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data Models
|
||||||
|
|
||||||
|
### DeviceRecord
|
||||||
|
```java
|
||||||
|
public class DeviceRecord {
|
||||||
|
public String address
|
||||||
|
public String title
|
||||||
|
public String broadcast
|
||||||
|
public String category
|
||||||
|
public String vendor
|
||||||
|
public String color
|
||||||
|
public int trackingMinutes
|
||||||
|
public boolean mapEnabled
|
||||||
|
public boolean liveEnabled
|
||||||
|
public boolean trackBroadcast
|
||||||
|
public boolean showTrail
|
||||||
|
public boolean locationLocked
|
||||||
|
public int txPower
|
||||||
|
public double exponent
|
||||||
|
public long lastSeen
|
||||||
|
public long lastLocation
|
||||||
|
public int battery
|
||||||
|
public String photo
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### LocationPoint
|
||||||
|
```java
|
||||||
|
public class LocationPoint {
|
||||||
|
public String address
|
||||||
|
public double latitude
|
||||||
|
public double longitude
|
||||||
|
public float accuracy
|
||||||
|
public long time
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Android Components
|
||||||
|
|
||||||
|
### Permissions Required
|
||||||
|
- `BLUETOOTH` - Bluetooth scanning and discovery
|
||||||
|
- `BLUETOOTH_ADMIN` - Bluetooth administration
|
||||||
|
- `ACCESS_FINE_LOCATION` - Precise location access
|
||||||
|
- `ACCESS_COARSE_LOCATION` - Approximate location access
|
||||||
|
- `FOREGROUND_SERVICE` - Background service execution
|
||||||
|
- `CAMERA` - Device photo capture
|
||||||
|
- `RECEIVE_BOOT_COMPLETED` - Auto-start on boot
|
||||||
|
|
||||||
|
### Services
|
||||||
|
- `BluetoothTrackingService` - Foreground service for continuous tracking
|
||||||
|
- `LocationManager` - GPS and network location services
|
||||||
|
- `BluetoothAdapter` - Bluetooth scanning and discovery
|
||||||
|
|
||||||
|
### Broadcast Receivers
|
||||||
|
- `DATA_CHANGED` - Device data updates
|
||||||
|
- `CONFIG_CHANGED` - Configuration changes
|
||||||
|
- `RANGE_MODE` - Range finder mode changes
|
||||||
|
- `BOOT_COMPLETED` - System boot completion
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Signal Processing Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
Bluetooth Scan → LeScanCallback → RSSI Reading
|
||||||
|
↓
|
||||||
|
BluetoothTrackingService
|
||||||
|
↓
|
||||||
|
captureFresh() → Fix()
|
||||||
|
↓
|
||||||
|
TrackerDatabase.recordObservation()
|
||||||
|
↓
|
||||||
|
SpatialGradientEngine Analysis
|
||||||
|
↓
|
||||||
|
RangeStateMachine State Update
|
||||||
|
↓
|
||||||
|
MapActivity / BluetoothRadarView Update
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Database Schema (Version 15)
|
||||||
|
|
||||||
|
### Tables
|
||||||
|
- `devices` - Device records and metadata
|
||||||
|
- `locations` - GPS location history
|
||||||
|
- `observations` - RSSI observations
|
||||||
|
- `telemetry` - Battery and vendor info
|
||||||
|
- `calibrations` - TX power and exponent
|
||||||
|
- `range_samples` - Range finding data
|
||||||
|
- `vendors` - Vendor lookup table
|
||||||
|
- `categories` - Device categories
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Document generated from technical analysis of Java source files*
|
||||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 364 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 472 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user