esim: show the profile icon image and its data size
pySim already requests the Icon tag (0x94) together with the other ProfileInfo tags; the mapping dropped it, so the PWA only had the icon type. - esim.profiles(): each profile now carries `icon` (the image bytes as hex) and `icon_size` (byte count), null when the card sent no image. - PWA: esimIconDataUrl() builds a data: URL (png/jpg -> image/png|jpeg) and the profile card shows the image unscaled to the left of the metadata rows; the Icon row keeps the type and adds the data size (e.g. 'png · 1234 B'). - tests: profiles icon/icon_size mapping (+ the absent case) and the frontend data URL / row / render checks; docs and sw simple-v231.
This commit is contained in:
+13
-3
@@ -12,7 +12,7 @@ from types import SimpleNamespace
|
||||
|
||||
from pySim.euicc import (
|
||||
AID_ISD_R, CardApplicationISDR, DisableProfileResp, DisableResult,
|
||||
EnableProfileResp, EnableResult,
|
||||
EnableProfileResp, EnableResult, Icon, IconType,
|
||||
Iccid, IsdpAid, ListNotificationResp, NotificationAddress,
|
||||
NotificationMetadata, NotificationMetadataList, ProfileClass, ProfileInfo,
|
||||
ProfileInfoListResp, ProfileInfoSeq, ProfileMgmtOperation, ProfileNickname,
|
||||
@@ -55,7 +55,8 @@ def make_app(profile='Consumer eUICC (SGP.22)', isdr=True):
|
||||
return SimpleNamespace(rs=rs), lchan
|
||||
|
||||
|
||||
def profile_info(iccid, aid, state=None, nickname=None, cls=None, owner=None):
|
||||
def profile_info(iccid, aid, state=None, nickname=None, cls=None, owner=None,
|
||||
icon=None):
|
||||
children = [Iccid(decoded=iccid), IsdpAid(decoded=bytes.fromhex(aid))]
|
||||
if state:
|
||||
children.append(ProfileState(decoded=state))
|
||||
@@ -65,6 +66,10 @@ def profile_info(iccid, aid, state=None, nickname=None, cls=None, owner=None):
|
||||
children.append(ProfileClass(decoded=cls))
|
||||
if owner:
|
||||
children.append(ProfileOwner(children=[ProfileOwnerPLMN(decoded=owner)]))
|
||||
if icon:
|
||||
icon_type, icon_data = icon
|
||||
children.append(IconType(decoded=icon_type))
|
||||
children.append(Icon(decoded=bytes.fromhex(icon_data)))
|
||||
return ProfileInfo(children=children)
|
||||
|
||||
|
||||
@@ -102,7 +107,7 @@ class EsimTests(unittest.TestCase):
|
||||
resp = ProfileInfoListResp(children=[ProfileInfoSeq(children=[
|
||||
profile_info('8970119000004002667', 'A0000005591010FFFFFFFF8900000100',
|
||||
state='enabled', nickname='Work', cls='operational',
|
||||
owner='250-99'),
|
||||
owner='250-99', icon=('png', '89504E470D0A1A0A')),
|
||||
profile_info('8970119000004002668', 'A0000005591010FFFFFFFF8900000200',
|
||||
state='disabled', cls='test'),
|
||||
])])
|
||||
@@ -117,7 +122,12 @@ class EsimTests(unittest.TestCase):
|
||||
self.assertEqual(first['nickname'], 'Work')
|
||||
self.assertEqual(first['class'], 'operational')
|
||||
self.assertEqual(first['owner'], '250-99')
|
||||
self.assertEqual(first['icon_type'], 'png')
|
||||
self.assertEqual(first['icon'], '89504E470D0A1A0A')
|
||||
self.assertEqual(first['icon_size'], 8)
|
||||
self.assertEqual(out['profiles'][1]['state'], 'disabled')
|
||||
self.assertIsNone(out['profiles'][1]['icon'])
|
||||
self.assertIsNone(out['profiles'][1]['icon_size'])
|
||||
# ISD-R was selected and the previous selection restored
|
||||
self.assertEqual(lchan.selected.name, 'ISD-R')
|
||||
self.assertEqual(app.rs.resets, 1)
|
||||
|
||||
Reference in New Issue
Block a user