Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 29 additions & 21 deletions cmd/kcd/cli_connectivity.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,42 @@ var connectivityCmd = &cli.Command{
},
}

// formatConnectivity renders one line per SIM, e.g. "LTE [███░] (3/4)".
// The primary SIM ("0", else lowest key) comes first; keys are sorted for
// stable output. Level is clamped to 0-4 so the bar always parses.
// signalDots renders signal level 0-4 as a four-position dot bar. The range is
// clamped so a bogus level from the phone still produces a parseable bar, and
// four positions means the maximum level reads as genuinely full.
// These are text-presentation geometric shapes (single cell width), not
// pictographs, so they align like the block-element bar they replace.
func signalDots(level int) string {
if level < 0 {
level = 0
}
if level > 4 {
level = 4
}
dots := []string{"○○○○", "●○○○", "●●○○", "●●●○", "●●●●"}
return dots[level]
}

func formatSIMStatus(networkType string, level int) string {
if level <= 0 {
return "No service"
}
label := networkType
if label == "" || strings.EqualFold(label, "unknown") {
label = "Cellular"
}
return fmt.Sprintf("%-8s %s", label, signalDots(level))
}

func formatConnectivity(body connectivity.ConnectivityBody) []string {
if len(body.SignalStrengths) == 0 {
return []string{"No signal data reported"}
return []string{"No SIM or cellular data available"}
}
keys := make([]string, 0, len(body.SignalStrengths))
for k := range body.SignalStrengths {
keys = append(keys, k)
}
sort.Strings(keys)
// Primary SIM first.
if _, ok := body.SignalStrengths["0"]; ok {
ordered := []string{"0"}
for _, k := range keys {
Expand All @@ -77,26 +100,11 @@ func formatConnectivity(body connectivity.ConnectivityBody) []string {
lines := make([]string, 0, len(keys))
for _, k := range keys {
sig := body.SignalStrengths[k]
level := sig.SignalStrength
if level < 0 {
level = 0
}
if level > 4 {
level = 4
}
netType := sig.NetworkDetailedType
if netType == "" {
netType = sig.NetworkType
}
if netType == "" {
netType = "CELL"
}
bar := strings.Repeat("█", level) + strings.Repeat("░", 4-level)
if len(keys) == 1 {
lines = append(lines, fmt.Sprintf("%s [%s] (%d/4)", strings.ToUpper(netType), bar, level))
} else {
lines = append(lines, fmt.Sprintf("SIM %s: %s [%s] (%d/4)", k, strings.ToUpper(netType), bar, level))
}
lines = append(lines, fmt.Sprintf("SIM %s: %s", k, formatSIMStatus(netType, sig.SignalStrength)))
}
return lines
}
50 changes: 43 additions & 7 deletions cmd/kcd/cli_connectivity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,72 @@ func TestFormatConnectivity(t *testing.T) {
{
name: "empty",
body: connectivity.ConnectivityBody{},
want: []string{"No signal data reported"},
want: []string{"No SIM or cellular data available"},
},
{
name: "single sim detailed type",
body: connectivity.ConnectivityBody{SignalStrengths: map[string]connectivity.SignalStrength{
"0": {NetworkType: "LTE", NetworkDetailedType: "LTE", SignalStrength: 3},
}},
want: []string{"LTE [███░] (3/4)"},
want: []string{"SIM 0: LTE ●●●○"},
},
{
name: "falls back to network type",
body: connectivity.ConnectivityBody{SignalStrengths: map[string]connectivity.SignalStrength{
"0": {NetworkType: "5G", SignalStrength: 4},
}},
want: []string{"5G [████] (4/4)"},
want: []string{"SIM 0: 5G ●●●●"},
},
{
name: "clamps out of range",
name: "clamps above range to a full bar",
body: connectivity.ConnectivityBody{SignalStrengths: map[string]connectivity.SignalStrength{
"0": {NetworkType: "GSM", SignalStrength: 9},
}},
want: []string{"GSM [████] (4/4)"},
want: []string{"SIM 0: GSM ●●●●"},
},
{
name: "dual sim primary first",
name: "clamps below range reads as no service",
body: connectivity.ConnectivityBody{SignalStrengths: map[string]connectivity.SignalStrength{
"0": {NetworkType: "GSM", SignalStrength: -2},
}},
want: []string{"SIM 0: No service"},
},
{
name: "zero level is no service, not an empty bar",
body: connectivity.ConnectivityBody{SignalStrengths: map[string]connectivity.SignalStrength{
"0": {NetworkType: "LTE", SignalStrength: 0},
}},
want: []string{"SIM 0: No service"},
},
{
name: "unknown network type reads as cellular",
body: connectivity.ConnectivityBody{SignalStrengths: map[string]connectivity.SignalStrength{
"0": {NetworkType: "unknown", SignalStrength: 2},
}},
want: []string{"SIM 0: Cellular ●●○○"},
},
{
name: "empty network type reads as cellular",
body: connectivity.ConnectivityBody{SignalStrengths: map[string]connectivity.SignalStrength{
"0": {SignalStrength: 1},
}},
want: []string{"SIM 0: Cellular ●○○○"},
},
{
name: "dual sim primary first and labels stay aligned",
body: connectivity.ConnectivityBody{SignalStrengths: map[string]connectivity.SignalStrength{
"1": {NetworkType: "EDGE", SignalStrength: 2},
"0": {NetworkType: "LTE", SignalStrength: 4},
}},
want: []string{"SIM 0: LTE [████] (4/4)", "SIM 1: EDGE [██░░] (2/4)"},
want: []string{"SIM 0: LTE ●●●●", "SIM 1: EDGE ●●○○"},
},
{
name: "sparse subscription ids are not renumbered",
body: connectivity.ConnectivityBody{SignalStrengths: map[string]connectivity.SignalStrength{
"3": {NetworkType: "NR", SignalStrength: 3},
"7": {NetworkType: "LTE", SignalStrength: 1},
}},
want: []string{"SIM 3: NR ●●●○", "SIM 7: LTE ●○○○"},
},
}
for _, tc := range cases {
Expand Down
57 changes: 1 addition & 56 deletions cmd/kcd/cli_watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,62 +56,7 @@ var watchCmd = &cli.Command{
b, _ := json.Marshal(ev)
fmt.Println(string(b))
} else {
switch ev.Type {
case events.TypeBatteryUpdate:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("[%s] battery: %v%% (charging: %v)\n", ev.DeviceID, payload["charge"], payload["charging"])
case events.TypeNotification:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("[%s] notification: %s - %s\n", ev.DeviceID, payload["appName"], payload["title"])
case events.TypeShareProgress:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("\r[%s] transfer: %s... %v/%v bytes", ev.DeviceID, payload["file"], payload["current"], payload["total"])
case events.TypeShareComplete:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("\n[%s] transfer complete: %s\n", ev.DeviceID, payload["file"])
case events.TypeShareText:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("[%s] share text: %s\n", ev.DeviceID, payload["text"])
case events.TypeShareURL:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("[%s] share url: %s\n", ev.DeviceID, payload["url"])
case events.TypeSftpMount:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("[%s] SFTP credentials received: %s\n", ev.DeviceID, payload["uri"])
case events.TypePairRequested:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("[%s] pair request from %s (%s). code: %v\n", ev.DeviceID, payload["name"], payload["type"], payload["verificationKey"])
case events.TypePairAccepted:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("[%s] paired with %s\n", ev.DeviceID, payload["name"])
case events.TypePairRejected:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("[%s] pairing rejected or cancelled by %s\n", ev.DeviceID, payload["name"])
case events.TypeNotificationCanceled:
payload, _ := ev.Payload.(map[string]interface{})
fmt.Printf("[%s] notification cancelled: %s\n", ev.DeviceID, payload["id"])
case events.TypeMprisUpdate:
payload, _ := ev.Payload.(map[string]interface{})
state := "⏹"
if isPlaying, _ := payload["isPlaying"].(bool); isPlaying {
state = "▶"
} else if ps, _ := payload["playbackStatus"].(string); ps == "Paused" {
state = "⏸"
}
player, _ := payload["player"].(string)
title, _ := payload["title"].(string)
artist, _ := payload["artist"].(string)
fmt.Printf("[%s] %s %s", ev.DeviceID, state, player)
if title != "" {
fmt.Printf(" - %s", title)
}
if artist != "" {
fmt.Printf(" (%s)", artist)
}
fmt.Println()
default:
fmt.Printf("[%s] %s\n", ev.DeviceID, ev.Type)
}
fmt.Print(formatEvent(ev))
}
}
}()
Expand Down
Loading
Loading